Make WordPress Core


Ignore:
Timestamp:
07/07/2020 08:45:55 PM (5 years ago)
Author:
TimothyBlynJacobs
Message:

REST API, Meta: Introduce support for default metadata values.

The register_meta() API now officially supports specifying a default metadata value. When get_metadata() is called for a meta key that does not yet exist for the object, this default value will be returned instead of an empty string.

A new function is introduced get_metadata_raw to retrieve the raw metadata value from the database, without applying the registered default.

Props spacedmonkey, flixos90, rmccue, kadamwhite, mnelson4, johnbillion, chrisvanpatten, TimothyBlynJacobs.
Fixes #43941.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/meta.php

    r48214 r48402  
    211211    // Compare existing value to new value if no prev value given and the key exists only once.
    212212    if ( empty( $prev_value ) ) {
    213         $old_value = get_metadata( $meta_type, $object_id, $meta_key );
    214         if ( count( $old_value ) == 1 ) {
     213        $old_value = get_metadata_raw( $meta_type, $object_id, $meta_key );
     214        if ( is_countable( $old_value ) && count( $old_value ) === 1 ) {
    215215            if ( $old_value[0] === $meta_value ) {
    216216                return false;
     
    486486 * If there's a problem with the parameters passed to the function, boolean `false` is returned.
    487487 *
    488  * @since 2.9.0
     488 * @since 5.5.0
    489489 *
    490490 * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
     
    497497 * @return mixed The metadata value or array of values. See description above for further details.
    498498 */
    499 function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false ) {
     499function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = false ) {
    500500    if ( ! $meta_type || ! is_numeric( $object_id ) ) {
    501501        return false;
     
    554554    }
    555555
     556    return null;
     557}
     558
     559/**
     560 * Retrieves raw metadata for the specified object.
     561 *
     562 * @since 2.9.0
     563 * @uses get_metadata_raw()
     564 *
     565 * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
     566 *                          or any other object type with an associated meta table.
     567 * @param int    $object_id ID of the object metadata is for.
     568 * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
     569 *                          the specified object. Default empty.
     570 * @param bool   $single    Optional. If true, return only the first value of the specified meta_key.
     571 *                          This parameter has no effect if meta_key is not specified. Default false.
     572 * @return mixed Single metadata value, or array of values
     573 */
     574function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false ) {
     575    $value = get_metadata_raw( $meta_type, $object_id, $meta_key, $single );
     576    if ( ! is_null( $value ) ) {
     577        return $value;
     578    }
     579
     580    return get_metadata_default( $meta_type, $meta_key, $single, $object_id );
     581}
     582
     583/**
     584 * Retrieve metadata data default for the specified object.
     585 *
     586 * @since 5.5.0
     587 *
     588 * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
     589 * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
     590 *                          the specified object.
     591 * @param bool   $single    Optional, default is false.
     592 *                          If true, return only the first value of the specified meta_key.
     593 *                          This parameter has no effect if meta_key is not specified.
     594 * @param int    $object_id Optional, default is 0.
     595 *                          ID of the object metadata is for
     596 * @return mixed Single metadata value, or array of values
     597 */
     598function get_metadata_default( $meta_type, $meta_key, $single = false, $object_id = 0 ) {
    556599    if ( $single ) {
    557         return '';
     600        $value = '';
    558601    } else {
    559         return array();
    560     }
     602        $value = array();
     603    }
     604
     605    /**
     606     * Filter the default value a specified object.
     607     *
     608     * @since 5.5.0
     609     *
     610     * @param array|string      $value     The value should return - a single metadata value,
     611     *                                     or an array of values.
     612     * @param string            $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
     613     * @param string            $meta_key  Meta key.
     614     * @param bool              $single    Whether to return only the first value of the specified $meta_key.
     615     * @param int               $object_id Object ID.
     616     */
     617    $value = apply_filters( "default_{$meta_type}_metadata", $value, $meta_type, $meta_key, $single, $object_id );
     618
     619    if ( ! $single && ! wp_is_numeric_array( $value ) ) {
     620        $value = array( $value );
     621    }
     622
     623    return $value;
    561624}
    562625
     
    11641227 *     @type string     $description       A description of the data attached to this meta key.
    11651228 *     @type bool       $single            Whether the meta key has one value per object, or an array of values per object.
     1229 *     @type mixed      $default           The default value returned from {@see get_metadata()} if no value has been set yet.
     1230 *                                         When using a non-single meta key, the default value is for the first entry. In other
     1231 *                                         words, when calling {@see get_metadata()} with `$single` set to `false`, the default
     1232 *                                         value given here will be wrapped in an array.
    11661233 *     @type string     $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
    11671234 *     @type string     $auth_callback     Optional. A function or method to call when performing edit_post_meta,
     
    11891256        'type'              => 'string',
    11901257        'description'       => '',
     1258        'default'           => '',
    11911259        'single'            => false,
    11921260        'sanitize_callback' => null,
     
    12261294     */
    12271295    $args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
     1296    unset( $defaults['default'] );
    12281297    $args = wp_parse_args( $args, $defaults );
    12291298
     
    12621331        } else {
    12631332            add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
     1333        }
     1334    }
     1335
     1336    if ( array_key_exists( 'default', $args ) ) {
     1337        $schema = $args;
     1338        if ( is_array( $args['show_in_rest'] ) && isset( $args['show_in_rest']['schema'] ) ) {
     1339            $schema = array_merge( $schema, $args['show_in_rest']['schema'] );
     1340        }
     1341
     1342        $check = rest_validate_value_from_schema( $args['default'], $schema );
     1343        if ( is_wp_error( $check ) ) {
     1344            _doing_it_wrong( __FUNCTION__, __( 'When registering a default meta value the data must match the type provided.' ), '5.5.0' );
     1345
     1346            return false;
     1347        }
     1348
     1349        if ( ! has_filter( "default_{$object_type}_metadata", 'filter_default_metadata' ) ) {
     1350            add_filter( "default_{$object_type}_metadata", 'filter_default_metadata', 10, 5 );
    12641351        }
    12651352    }
     
    14971584    return apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
    14981585}
     1586
     1587/**
     1588 * Filter into default_{$object_type}_metadata and add in default value.
     1589 *
     1590 * @since 5.5.0
     1591 *
     1592 * @param mixed  $value     Current value passed to filter.
     1593 * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
     1594
     1595 * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
     1596 *                          the specified object.
     1597 * @param bool   $single    Optional, default is false.
     1598 *                          If true, return only the first value of the specified meta_key.
     1599 *                          This parameter has no effect if meta_key is not specified.
     1600 * @param int    $object_id ID of the object metadata is for
     1601 *
     1602 * @return mixed Single metadata default, or array of defaults
     1603 */
     1604function filter_default_metadata( $value, $meta_type, $meta_key, $single, $object_id ) {
     1605    global $wp_meta_keys;
     1606
     1607    if ( wp_installing() ) {
     1608        return $value;
     1609    }
     1610
     1611    if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $meta_type ] ) ) {
     1612        return $value;
     1613    }
     1614
     1615    $defaults = array();
     1616    foreach ( $wp_meta_keys[ $meta_type ] as $sub_type => $meta_data ) {
     1617        foreach ( $meta_data as $_meta_key => $args ) {
     1618            if ( $_meta_key === $meta_key && array_key_exists( 'default', $args ) ) {
     1619                $defaults[ $sub_type ] = $args;
     1620            }
     1621        }
     1622    }
     1623
     1624    if ( ! $defaults ) {
     1625        return $value;
     1626    }
     1627
     1628    // If this meta type does not have sub types, then the default is keyed as an empty string.
     1629    if ( isset( $defaults[''] ) ) {
     1630        $metadata = $defaults[''];
     1631    } else {
     1632        $sub_type = get_object_subtype( $meta_type, $object_id );
     1633        if ( ! isset( $defaults[ $sub_type ] ) ) {
     1634            return $value;
     1635        }
     1636        $metadata = $defaults[ $sub_type ];
     1637    }
     1638
     1639    if ( $single ) {
     1640        $value = $metadata['default'];
     1641    } else {
     1642        $value = array( $metadata['default'] );
     1643    }
     1644
     1645    return $value;
     1646}
Note: See TracChangeset for help on using the changeset viewer.