WordPress Version: 6.4
/**
* Registers a meta key.
*
* It is recommended to register meta keys for a specific combination of object type and object subtype. If passing
* an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly
* overridden in case a more specific meta key of the same name exists for the same object type and a subtype.
*
* If an object type does not support any subtypes, such as users or comments, you should commonly call this function
* without passing a subtype.
*
* @since 3.3.0
* @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified
* to support an array of data to attach to registered meta keys}. Previous arguments for
* `$sanitize_callback` and `$auth_callback` have been folded into this array.
* @since 4.9.8 The `$object_subtype` argument was added to the arguments array.
* @since 5.3.0 Valid meta types expanded to include "array" and "object".
* @since 5.5.0 The `$default` argument was added to the arguments array.
* @since 6.4.0 The `$revisions_enabled` argument was added to the arguments array.
*
* @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
* or any other object type with an associated meta table.
* @param string $meta_key Meta key to register.
* @param array $args {
* Data used to describe the meta key when registered.
*
* @type string $object_subtype A subtype; e.g. if the object type is "post", the post type. If left empty,
* the meta key will be registered on the entire object type. Default empty.
* @type string $type The type of data associated with this meta key.
* Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'.
* @type string $description A description of the data attached to this meta key.
* @type bool $single Whether the meta key has one value per object, or an array of values per object.
* @type mixed $default The default value returned from get_metadata() if no value has been set yet.
* When using a non-single meta key, the default value is for the first entry.
* In other words, when calling get_metadata() with `$single` set to `false`,
* the default value given here will be wrapped in an array.
* @type callable $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
* @type callable $auth_callback Optional. A function or method to call when performing edit_post_meta,
* add_post_meta, and delete_post_meta capability checks.
* @type bool|array $show_in_rest Whether data associated with this meta key can be considered public and
* should be accessible via the REST API. A custom post type must also declare
* support for custom fields for registered meta to be accessible via REST.
* When registering complex meta values this argument may optionally be an
* array with 'schema' or 'prepare_callback' keys instead of a boolean.
* @type bool $revisions_enabled Whether to enable revisions support for this meta_key. Can only be used when the
* object type is 'post'.
* }
* @param string|array $deprecated Deprecated. Use `$args` instead.
* @return bool True if the meta key was successfully registered in the global array, false if not.
* Registering a meta key with distinct sanitize and auth callbacks will fire those callbacks,
* but will not add to the global registry.
*/
function register_meta($object_type, $meta_key, $args, $deprecated = null)
{
global $wp_meta_keys;
if (!is_array($wp_meta_keys)) {
$wp_meta_keys = array();
}
$defaults = array('object_subtype' => '', 'type' => 'string', 'description' => '', 'default' => '', 'single' => false, 'sanitize_callback' => null, 'auth_callback' => null, 'show_in_rest' => false, 'revisions_enabled' => false);
// There used to be individual args for sanitize and auth callbacks.
$has_old_sanitize_cb = false;
$has_old_auth_cb = false;
if (is_callable($args)) {
$args = array('sanitize_callback' => $args);
$has_old_sanitize_cb = true;
} else {
$args = (array) $args;
}
if (is_callable($deprecated)) {
$args['auth_callback'] = $deprecated;
$has_old_auth_cb = true;
}
/**
* Filters the registration arguments when registering meta.
*
* @since 4.6.0
*
* @param array $args Array of meta registration arguments.
* @param array $defaults Array of default arguments.
* @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
* or any other object type with an associated meta table.
* @param string $meta_key Meta key.
*/
$args = apply_filters('register_meta_args', $args, $defaults, $object_type, $meta_key);
unset($defaults['default']);
$args = wp_parse_args($args, $defaults);
// Require an item schema when registering array meta.
if (false !== $args['show_in_rest'] && 'array' === $args['type']) {
if (!is_array($args['show_in_rest']) || !isset($args['show_in_rest']['schema']['items'])) {
_doing_it_wrong(__FUNCTION__, __('When registering an "array" meta type to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".'), '5.3.0');
return false;
}
}
$object_subtype = (!empty($args['object_subtype'])) ? $args['object_subtype'] : '';
if ($args['revisions_enabled']) {
if ('post' !== $object_type) {
_doing_it_wrong(__FUNCTION__, __('Meta keys cannot enable revisions support unless the object type supports revisions.'), '6.4.0');
return false;
} elseif (!empty($object_subtype) && !post_type_supports($object_subtype, 'revisions')) {
_doing_it_wrong(__FUNCTION__, __('Meta keys cannot enable revisions support unless the object subtype supports revisions.'), '6.4.0');
return false;
}
}
// If `auth_callback` is not provided, fall back to `is_protected_meta()`.
if (empty($args['auth_callback'])) {
if (is_protected_meta($meta_key, $object_type)) {
$args['auth_callback'] = '__return_false';
} else {
$args['auth_callback'] = '__return_true';
}
}
// Back-compat: old sanitize and auth callbacks are applied to all of an object type.
if (is_callable($args['sanitize_callback'])) {
if (!empty($object_subtype)) {
add_filter("sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'], 10, 4);
} else {
add_filter("sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3);
}
}
if (is_callable($args['auth_callback'])) {
if (!empty($object_subtype)) {
add_filter("auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'], 10, 6);
} else {
add_filter("auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6);
}
}
if (array_key_exists('default', $args)) {
$schema = $args;
if (is_array($args['show_in_rest']) && isset($args['show_in_rest']['schema'])) {
$schema = array_merge($schema, $args['show_in_rest']['schema']);
}
$check = rest_validate_value_from_schema($args['default'], $schema);
if (is_wp_error($check)) {
_doing_it_wrong(__FUNCTION__, __('When registering a default meta value the data must match the type provided.'), '5.5.0');
return false;
}
if (!has_filter("default_{$object_type}_metadata", 'filter_default_metadata')) {
add_filter("default_{$object_type}_metadata", 'filter_default_metadata', 10, 5);
}
}
// Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
if (!$has_old_auth_cb && !$has_old_sanitize_cb) {
unset($args['object_subtype']);
$wp_meta_keys[$object_type][$object_subtype][$meta_key] = $args;
return true;
}
return false;
}