Make WordPress Core

Ticket #55942: 55942.diff

File 55942.diff, 38.0 KB (added by azaozz, 14 months ago)

Latest patch.

  • src/wp-includes/comment.php

    diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php
    index b732f83ad4e6..7343e5d81ab7 100644
    a b function delete_comment_meta( $comment_id, $meta_key, $meta_value = '' ) { 
    466466 * Retrieves comment meta field for a comment.
    467467 *
    468468 * @since 2.9.0
     469 * @since 6.3.0 Introduced the `$value_type` parameter.
    469470 *
    470471 * @link https://developer.wordpress.org/reference/functions/get_comment_meta/
    471472 *
    function delete_comment_meta( $comment_id, $meta_key, $meta_value = '' ) { 
    475476 * @param bool   $single     Optional. Whether to return a single value.
    476477 *                           This parameter has no effect if `$key` is not specified.
    477478 *                           Default false.
     479 * @param string $value_type Optional. The expected data type of the value.
    478480 * @return mixed An array of values if `$single` is false.
    479481 *               The value of meta data field if `$single` is true.
    480482 *               False for an invalid `$comment_id` (non-numeric, zero, or negative value).
    481483 *               An empty string if a valid but non-existing comment ID is passed.
    482484 */
    483 function get_comment_meta( $comment_id, $key = '', $single = false ) {
    484         return get_metadata( 'comment', $comment_id, $key, $single );
     485function get_comment_meta( $comment_id, $key = '', $single = false, $value_type = '' ) {
     486        return get_metadata( 'comment', $comment_id, $key, $single, $value_type );
    485487}
    486488
    487489/**
  • src/wp-includes/functions.php

    diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
    index 3267120b6f30..d67a72dea226 100644
    a b function is_php_version_compatible( $required ) { 
    85848584function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
    85858585        return abs( (float) $expected - (float) $actual ) <= $precision;
    85868586}
     8587
     8588/**
     8589 * Get supported data types for meta and option values.
     8590 *
     8591 * This is a subset of the PHP data types that can be used for
     8592 * meta and option values. See the documentation for PHP's 'settype()'.
     8593 *
     8594 * @since 6.3.0
     8595 *
     8596 * @return array List of supported value types.
     8597 */
     8598function wp_get_db_value_types() {
     8599        return array(
     8600                'boolean',
     8601                'bool',
     8602                'integer',
     8603                'int',
     8604                'float',
     8605                'string',
     8606                'array',
     8607                'object',
     8608        );
     8609}
     8610
     8611/**
     8612 * Set the type of a meta or option value that was retrieved from the database.
     8613 *
     8614 * If `$value_type` is empty, the value is returned unchanged. If `$value_type` is not one
     8615 * of the expected types, a user error is triggered and the value is returned unchanged.
     8616 *
     8617 * @since 6.3.0
     8618 *
     8619 * @param mixed  $value      Raw value from the database.
     8620 * @param string $value_type The expected value type.
     8621 * @return mixed The value with the requested type.
     8622 */
     8623function wp_settype_to_value_from_db( $value, $value_type ) {
     8624        if ( ! empty( $value_type ) ) {
     8625                $value_types = wp_get_db_value_types();
     8626
     8627                if ( in_array( $value_type, $value_types, true ) ) {
     8628                        settype( $value, $value_type );
     8629                } else {
     8630                        // Improper use.
     8631                        /* translators: The function name that returns the supported types. */
     8632                        $message = sprintf( __( 'Only types returned by %s are supported.' ), '<code>wp_get_db_value_types()</code>' );
     8633                        _doing_it_wrong( 'wp_settype_to_value_from_db', $message );
     8634                }
     8635        }
     8636
     8637        return $value;
     8638}
     8639
     8640
     8641/**
     8642 * Decode a value after it was retrieved from the database.
     8643 *
     8644 * Unserialize the value if needed, and set it to the expected type.
     8645 * Intended for use with option and meta values.
     8646 *
     8647 * @since 6.3.0
     8648 *
     8649 * @param mixed  $value      Raw value from the database.
     8650 * @param string $value_type Optional. The expected value type.
     8651 * @return mixed The decoded value.
     8652 */
     8653function wp_decode_value_from_db( $value, $value_type = '' ) {
     8654        $original_value = $value;
     8655
     8656        if ( empty( $value_type ) ) {
     8657                $value = maybe_unserialize( $value );
     8658        } else {
     8659                if ( 'array' === $value_type || 'object' === $value_type ) {
     8660                        $value = maybe_unserialize( $value );
     8661                }
     8662
     8663                $value = wp_settype_to_value_from_db( $value, $value_type );
     8664        }
     8665
     8666        /**
     8667         * Filter the decoded value.
     8668         *
     8669         * @since 6.3.0
     8670         *
     8671         * @param mixed  $value          Decoded value.
     8672         * @param mixed  $original_value Original value from the database.
     8673         * @param string $value_type     The expected value type.
     8674         */
     8675        return apply_filters( 'wp_decode_value_from_db', $value, $original_value, $value_type );
     8676}
  • src/wp-includes/meta.php

    diff --git a/src/wp-includes/meta.php b/src/wp-includes/meta.php
    index 2b5ca02696c2..b1e3b297dd7e 100644
    a b function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $ 
    552552 * By default, an empty string is returned if `$single` is true, or an empty array
    553553 * if it's false.
    554554 *
     555 * In most cases non-string scalar and null values will be converted and returned
     556 * as string equivalents if the `$value_type` paramenter is not set. If it is set
     557 * the values will be of the expected type.
     558 *
    555559 * @since 2.9.0
     560 * @since 6.3.0 Introduced the `$value_type` parameter.
    556561 *
    557562 * @see get_metadata_raw()
    558563 * @see get_metadata_default()
    559564 *
    560  * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
    561  *                          or any other object type with an associated meta table.
    562  * @param int    $object_id ID of the object metadata is for.
    563  * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
    564  *                          the specified object. Default empty string.
    565  * @param bool   $single    Optional. If true, return only the first value of the specified `$meta_key`.
    566  *                          This parameter has no effect if `$meta_key` is not specified. Default false.
     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 string.
     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 * @param string $value_type Optional. The expected data type of the value.
    567573 * @return mixed An array of values if `$single` is false.
    568574 *               The value of the meta field if `$single` is true.
    569575 *               False for an invalid `$object_id` (non-numeric, zero, or negative value),
    570576 *               or if `$meta_type` is not specified.
    571577 *               An empty string if a valid but non-existing object ID is passed.
    572578 */
    573 function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false ) {
    574         $value = get_metadata_raw( $meta_type, $object_id, $meta_key, $single );
     579function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false, $value_type = '' ) {
     580        $value = get_metadata_raw( $meta_type, $object_id, $meta_key, $single, $value_type );
    575581        if ( ! is_null( $value ) ) {
    576582                return $value;
    577583        }
    function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false ) 
    583589 * Retrieves raw metadata value for the specified object.
    584590 *
    585591 * @since 5.5.0
     592 * @since 6.3.0 Introduced the `$value_type` parameter.
    586593 *
    587  * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
    588  *                          or any other object type with an associated meta table.
    589  * @param int    $object_id ID of the object metadata is for.
    590  * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
    591  *                          the specified object. Default empty string.
    592  * @param bool   $single    Optional. If true, return only the first value of the specified `$meta_key`.
    593  *                          This parameter has no effect if `$meta_key` is not specified. Default false.
     594 * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
     595 *                           or any other object type with an associated meta table.
     596 * @param int    $object_id  ID of the object metadata is for.
     597 * @param string $meta_key   Optional. Metadata key. If not specified, retrieve all metadata for
     598 *                           the specified object. Default empty string.
     599 * @param bool   $single     Optional. If true, return only the first value of the specified `$meta_key`.
     600 *                           This parameter has no effect if `$meta_key` is not specified. Default false.
     601 * @param string $value_type Optional. The expected data type of the value.
    594602 * @return mixed An array of values if `$single` is false.
    595603 *               The value of the meta field if `$single` is true.
    596604 *               False for an invalid `$object_id` (non-numeric, zero, or negative value),
    597605 *               or if `$meta_type` is not specified.
    598606 *               Null if the value does not exist.
    599607 */
    600 function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = false ) {
     608function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = false, $value_type = '' ) {
    601609        if ( ! $meta_type || ! is_numeric( $object_id ) ) {
    602610                return false;
    603611        }
    function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal 
    614622         * (post, comment, term, user, or any other type with an associated meta table).
    615623         * Returning a non-null value will effectively short-circuit the function.
    616624         *
     625         * The filter assumes that a numeric array is always returned similarly to the return value
     626         * from {@see 'update_meta_cache()'}. Returning `false` is also acceptable to signify
     627         * incorrect parameters.
     628         *
    617629         * Possible filter names include:
    618630         *
    619631         *  - `get_post_metadata`
    function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal 
    623635         *
    624636         * @since 3.1.0
    625637         * @since 5.5.0 Added the `$meta_type` parameter.
    626          *
    627          * @param mixed  $value     The value to return, either a single metadata value or an array
    628          *                          of values depending on the value of `$single`. Default null.
    629          * @param int    $object_id ID of the object metadata is for.
    630          * @param string $meta_key  Metadata key.
    631          * @param bool   $single    Whether to return only the first value of the specified `$meta_key`.
    632          * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
    633          *                          or any other object type with an associated meta table.
     638         * @since 6.3.0 Added the `$value_type` parameter.
     639         *
     640         * @param mixed  $value      Numeric array of one or more meta values. Default null.
     641         * @param int    $object_id  ID of the object metadata is for.
     642         * @param string $meta_key   Metadata key.
     643         * @param bool   $single     Whether to return only the first value of the specified `$meta_key`.
     644         *                           If `true` only the first element of the filtered array is returned.
     645         * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
     646         *                           or any other object type with an associated meta table.
     647         * @param string $value_type The expected data type of the value.
    634648         */
    635         $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single, $meta_type );
    636         if ( null !== $check ) {
    637                 if ( $single && is_array( $check ) ) {
    638                         return $check[0];
     649        $pre_meta = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single, $meta_type, $value_type );
     650        if ( null !== $pre_meta ) {
     651                // `false` is an expected return value in some cases. See above.
     652                if ( false === $pre_meta ) {
     653                        return $pre_meta;
     654                }
     655
     656                if ( $single ) {
     657                        // A numeric array is expected especiually if the meta value is also an array.
     658                        if ( is_array( $pre_meta ) && isset( $pre_meta[0] ) ) {
     659                                $pre_meta = $pre_meta[0];
     660                        }
     661                        // Ensure the meta value is of the expected type after the filter.
     662                        return wp_settype_to_value_from_db( $pre_meta, $value_type );
    639663                } else {
    640                         return $check;
     664                        if ( is_array( $pre_meta ) ) {
     665                                foreach ( $pre_meta as $key => $meta_value ) {
     666                                        $pre_meta[ $key ] = wp_settype_to_value_from_db( $meta_value, $value_type );
     667                                }
     668                        } else {
     669                                $pre_meta = wp_settype_to_value_from_db( $pre_meta, $value_type );
     670                        }
     671
     672                        return $pre_meta;
    641673                }
    642674        }
    643675
    function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal 
    645677
    646678        if ( ! $meta_cache ) {
    647679                $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
     680
    648681                if ( isset( $meta_cache[ $object_id ] ) ) {
    649682                        $meta_cache = $meta_cache[ $object_id ];
    650683                } else {
    function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal 
    658691
    659692        if ( isset( $meta_cache[ $meta_key ] ) ) {
    660693                if ( $single ) {
    661                         return maybe_unserialize( $meta_cache[ $meta_key ][0] );
     694                        return wp_decode_value_from_db( $meta_cache[ $meta_key ][0], $value_type );
    662695                } else {
    663                         return array_map( 'maybe_unserialize', $meta_cache[ $meta_key ] );
     696                        $meta_values = $meta_cache[ $meta_key ];
     697
     698                        foreach ( (array) $meta_values as $key => $meta_value ) {
     699                                $meta_values[ $key ] = wp_decode_value_from_db( $meta_value, $value_type );
     700                        }
     701
     702                        return $meta_values;
    664703                }
    665704        }
    666705
    function metadata_exists( $meta_type, $object_id, $meta_key ) { 
    768807 * Retrieves metadata by meta ID.
    769808 *
    770809 * @since 3.3.0
     810 * @since 6.3.0 Introduced the `$value_type` parameter.
    771811 *
    772812 * @global wpdb $wpdb WordPress database abstraction object.
    773813 *
    774  * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
    775  *                          or any other object type with an associated meta table.
    776  * @param int    $meta_id   ID for a specific meta row.
     814 * @param string $meta_type  Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user',
     815 *                           or any other object type with an associated meta table.
     816 * @param int    $meta_id    ID for a specific meta row.
     817 * @param string $value_type Optional. The expected data type of the value.
    777818 * @return stdClass|false {
    778819 *     Metadata object, or boolean `false` if the metadata doesn't exist.
    779820 *
    function metadata_exists( $meta_type, $object_id, $meta_key ) { 
    787828 *     @type string $user_id    Optional. The object ID when the meta type is 'user'.
    788829 * }
    789830 */
    790 function get_metadata_by_mid( $meta_type, $meta_id ) {
     831function get_metadata_by_mid( $meta_type, $meta_id, $value_type = '' ) {
    791832        global $wpdb;
    792833
    793834        if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
    function get_metadata_by_mid( $meta_type, $meta_id ) { 
    820861         *
    821862         * @since 5.0.0
    822863         *
    823          * @param stdClass|null $value   The value to return.
    824          * @param int           $meta_id Meta ID.
     864         * @param stdClass|null $value      The value to return.
     865         * @param int           $meta_id    Meta ID.
     866         * @param string        $value_type The expected data type of the value.
    825867         */
    826         $check = apply_filters( "get_{$meta_type}_metadata_by_mid", null, $meta_id );
    827         if ( null !== $check ) {
    828                 return $check;
     868        $pre_meta = apply_filters( "get_{$meta_type}_metadata_by_mid", null, $meta_id, $value_type );
     869        if ( null !== $pre_meta ) {
     870                // Ensure the returned meta value is of the expected type.
     871                if ( is_object( $pre_meta ) && isset( $pre_meta->meta_value ) ) {
     872                        $pre_meta->meta_value = wp_settype_to_value_from_db( $pre_meta->meta_value, $value_type );
     873                }
     874
     875                return $pre_meta;
    829876        }
    830877
    831878        $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
    function get_metadata_by_mid( $meta_type, $meta_id ) { 
    837884        }
    838885
    839886        if ( isset( $meta->meta_value ) ) {
    840                 $meta->meta_value = maybe_unserialize( $meta->meta_value );
     887                $meta->meta_value = wp_decode_value_from_db( $meta->meta_value, $value_type );
    841888        }
    842889
    843890        return $meta;
  • src/wp-includes/ms-site.php

    diff --git a/src/wp-includes/ms-site.php b/src/wp-includes/ms-site.php
    index 486fad241424..7f5311f20054 100644
    a b function delete_site_meta( $site_id, $meta_key, $meta_value = '' ) { 
    10611061 * Retrieves metadata for a site.
    10621062 *
    10631063 * @since 5.1.0
     1064 * @since 6.3.0 Introduced the `$value_type` parameter.
    10641065 *
    1065  * @param int    $site_id Site ID.
    1066  * @param string $key     Optional. The meta key to retrieve. By default,
    1067  *                        returns data for all keys. Default empty.
    1068  * @param bool   $single  Optional. Whether to return a single value.
    1069  *                        This parameter has no effect if `$key` is not specified.
    1070  *                        Default false.
     1066 * @param int    $site_id    Site ID.
     1067 * @param string $key        Optional. The meta key to retrieve. By default,
     1068 *                           returns data for all keys. Default empty.
     1069 * @param bool   $single     Optional. Whether to return a single value.
     1070 *                           This parameter has no effect if `$key` is not specified.
     1071 *                           Default false.
     1072 * @param string $value_type Optional. The expected data type of the value.
    10711073 * @return mixed An array of values if `$single` is false.
    10721074 *               The value of meta data field if `$single` is true.
    10731075 *               False for an invalid `$site_id` (non-numeric, zero, or negative value).
    10741076 *               An empty string if a valid but non-existing site ID is passed.
    10751077 */
    1076 function get_site_meta( $site_id, $key = '', $single = false ) {
    1077         return get_metadata( 'blog', $site_id, $key, $single );
     1078function get_site_meta( $site_id, $key = '', $single = false, $value_type = '' ) {
     1079        return get_metadata( 'blog', $site_id, $key, $single, $value_type );
    10781080}
    10791081
    10801082/**
  • src/wp-includes/option.php

    diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php
    index 48e8676ed2ac..8e00a0d93c7d 100644
    a b  
    1818 * Not initializing an option and using boolean `false` as a return value
    1919 * is a bad practice as it triggers an additional database query.
    2020 *
    21  * The type of the returned value can be different from the type that was passed
     21 * When the `$value_type` paramenter is not set the type
     22 * of the returned value may be different from the type that was passed
    2223 * when saving or updating the option. If the option value was serialized,
    2324 * then it will be unserialized when it is returned. In this case the type will
    2425 * be the same. For example, storing a non-scalar value like an array will
    2526 * return the same array.
    2627 *
    2728 * In most cases non-string scalar and null values will be converted and returned
    28  * as string equivalents.
     29 * as string equivalents if the `$value_type` paramenter is not set. If it is set
     30 * the values will be of the expected type.
    2931 *
    3032 * Exceptions:
    3133 *
     
    3537 *    {@see 'default_option_$option'}, or {@see 'option_$option'}, the returned
    3638 *    value may not match the expected type.
    3739 * 3. When the option has just been saved in the database, and get_option()
    38  *    is used right after, non-string scalar and null values are not converted to
    39  *    string equivalents and the original type is returned.
     40 *    is used right after without the `$value_type` paramenter, non-string scalar
     41 *    and null values are not converted to string equivalents and are returned with
     42 *    their original types.
    4043 *
    4144 * Examples:
    4245 *
     
    5255 *   - `'1'`   returns `string(1) "1"`
    5356 *   - `null`  returns `string(0) ""`
    5457 *
     58 * When the `$value_type` parameter is used the returned value will be of the expected type.
     59 * Retrieving the first option from the above example with
     60 * `get_option( 'my_option_name', false, 'boolean' )` will return `boolean false`.
     61 * Retrieving the second example will return `boolean true`. Retrieving the third example
     62 * with `get_option( 'my_option_name', false, 'integer' )` will return `integer 0`, etc.
    5563 * When adding options with non-scalar values like
    5664 * `add_option( 'my_array', array( false, 'str', null ) )`, the returned value
    57  * will be identical to the original as it is serialized before saving
     65 * will always be identical to the original as it is serialized before saving
    5866 * it in the database:
    5967 *
    6068 *     array(3) {
     
    6472 *     }
    6573 *
    6674 * @since 1.5.0
     75 * @since 6.3.0 Introduced the `$value_type` parameter.
    6776 *
    6877 * @global wpdb $wpdb WordPress database abstraction object.
    6978 *
    7079 * @param string $option        Name of the option to retrieve. Expected to not be SQL-escaped.
    7180 * @param mixed  $default_value Optional. Default value to return if the option does not exist.
     81 * @param string $value_type    Optional. The expected data type of the value.
    7282 * @return mixed Value of the option. A value of any type may be returned, including
    7383 *               scalar (string, boolean, float, integer), null, array, object.
    7484 *               Scalar and null values will be returned as strings as long as they originate
    7585 *               from a database stored option value. If there is no option in the database,
    7686 *               boolean `false` is returned.
    7787 */
    78 function get_option( $option, $default_value = false ) {
     88function get_option( $option, $default_value = false, $value_type = '' ) {
    7989        global $wpdb;
    8090
    8191        if ( is_scalar( $option ) ) {
    function get_option( $option, $default_value = false ) { 
    106116                                $deprecated_keys[ $option ]
    107117                        )
    108118                );
    109                 return get_option( $deprecated_keys[ $option ], $default_value );
     119                return get_option( $deprecated_keys[ $option ], $default_value, $value_type );
    110120        }
    111121
    112122        /**
    function get_option( $option, $default_value = false ) { 
    128138         * @param string $option        Option name.
    129139         * @param mixed  $default_value The fallback value to return if the option does not exist.
    130140         *                              Default false.
     141         * @param string $value_type    The expected data type of the value.
    131142         */
    132         $pre = apply_filters( "pre_option_{$option}", false, $option, $default_value );
     143        $pre = apply_filters( "pre_option_{$option}", false, $option, $default_value, $value_type );
    133144
    134145        /**
    135146         * Filters the value of all existing options before it is retrieved.
    function get_option( $option, $default_value = false ) { 
    146157         * @param string $option        Name of the option.
    147158         * @param mixed  $default_value The fallback value to return if the option does not exist.
    148159         *                              Default false.
     160         * @param string $value_type    The expected data type of the value.
    149161         */
    150         $pre = apply_filters( 'pre_option', $pre, $option, $default_value );
     162        $pre = apply_filters( 'pre_option', $pre, $option, $default_value, $value_type );
    151163
    152164        if ( false !== $pre ) {
    153                 return $pre;
     165                // Ensure the option value is of the expected type after the filters.
     166                return wp_settype_to_value_from_db( $pre, $value_type );
    154167        }
    155168
    156169        if ( defined( 'WP_SETUP_CONFIG' ) ) {
    function get_option( $option, $default_value = false ) { 
    184197                         *                               in the database.
    185198                         * @param string $option         Option name.
    186199                         * @param bool   $passed_default Was `get_option()` passed a default value?
     200                         * @param string $value_type     The expected data type of the value.
    187201                         */
    188                         return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default );
     202                        return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default, $value_type );
    189203                }
    190204
    191205                $alloptions = wp_load_alloptions();
    function get_option( $option, $default_value = false ) { 
    211225                                        wp_cache_set( 'notoptions', $notoptions, 'options' );
    212226
    213227                                        /** This filter is documented in wp-includes/option.php */
    214                                         return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default );
     228                                        return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default, $value_type );
    215229                                }
    216230                        }
    217231                }
    function get_option( $option, $default_value = false ) { 
    224238                        $value = $row->option_value;
    225239                } else {
    226240                        /** This filter is documented in wp-includes/option.php */
    227                         return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default );
     241                        return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default, $value_type );
    228242                }
    229243        }
    230244
    function get_option( $option, $default_value = false ) { 
    237251                $value = untrailingslashit( $value );
    238252        }
    239253
     254        $value = wp_decode_value_from_db( $value, $value_type );
     255
    240256        /**
    241257         * Filters the value of an existing option.
    242258         *
    function get_option( $option, $default_value = false ) { 
    246262         * @since 3.0.0
    247263         * @since 4.4.0 The `$option` parameter was added.
    248264         *
    249          * @param mixed  $value  Value of the option. If stored serialized, it will be
    250          *                       unserialized prior to being returned.
    251          * @param string $option Option name.
     265         * @param mixed  $value      Value of the option. If stored serialized, it will be
     266         *                           unserialized prior to being returned.
     267         * @param string $option     Option name.
     268         * @param string $value_type The expected data type of the value.
    252269         */
    253         return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
     270        return apply_filters( "option_{$option}", $value, $option, $value_type );
    254271}
    255272
    256273/**
    function update_site_option( $option, $value ) { 
    14151432 * Retrieves a network's option value based on the option name.
    14161433 *
    14171434 * @since 4.4.0
     1435 * @since 6.3.0 Introduced the `$value_type` parameter.
    14181436 *
    14191437 * @see get_option()
    14201438 *
    function update_site_option( $option, $value ) { 
    14231441 * @param int    $network_id    ID of the network. Can be null to default to the current network ID.
    14241442 * @param string $option        Name of the option to retrieve. Expected to not be SQL-escaped.
    14251443 * @param mixed  $default_value Optional. Value to return if the option doesn't exist. Default false.
     1444 * @param string $value_type    Optional. The expected data type of the value.
    14261445 * @return mixed Value set for the option.
    14271446 */
    1428 function get_network_option( $network_id, $option, $default_value = false ) {
     1447function get_network_option( $network_id, $option, $default_value = false, $value_type = '' ) {
    14291448        global $wpdb;
    14301449
    14311450        if ( $network_id && ! is_numeric( $network_id ) ) {
    function get_network_option( $network_id, $option, $default_value = false ) { 
    14611480         * @param int    $network_id    ID of the network.
    14621481         * @param mixed  $default_value The fallback value to return if the option does not exist.
    14631482         *                              Default false.
     1483         * @param string $value_type    The expected data type of the value.
    14641484         */
    1465         $pre = apply_filters( "pre_site_option_{$option}", false, $option, $network_id, $default_value );
     1485        $pre = apply_filters( "pre_site_option_{$option}", false, $option, $network_id, $default_value, $value_type );
    14661486
    14671487        if ( false !== $pre ) {
    1468                 return $pre;
     1488                // Ensure the option value is of the expected type after the filter.
     1489                return wp_settype_to_value_from_db( $pre, $value_type );
    14691490        }
    14701491
    14711492        // Prevent non-existent options from triggering multiple queries.
    function get_network_option( $network_id, $option, $default_value = false ) { 
    14871508                 *                              in the database.
    14881509                 * @param string $option        Option name.
    14891510                 * @param int    $network_id    ID of the network.
     1511                 * @param string $value_type    The expected data type of the value.
    14901512                 */
    1491                 return apply_filters( "default_site_option_{$option}", $default_value, $option, $network_id );
     1513                return apply_filters( "default_site_option_{$option}", $default_value, $option, $network_id, $value_type );
    14921514        }
    14931515
    14941516        if ( ! is_multisite() ) {
    14951517                /** This filter is documented in wp-includes/option.php */
    14961518                $default_value = apply_filters( 'default_site_option_' . $option, $default_value, $option, $network_id );
    1497                 $value         = get_option( $option, $default_value );
     1519                $value         = get_option( $option, $default_value, $value_type );
    14981520        } else {
    14991521                $cache_key = "$network_id:$option";
    15001522                $value     = wp_cache_get( $cache_key, 'site-options' );
    function get_network_option( $network_id, $option, $default_value = false ) { 
    15051527                        // Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
    15061528                        if ( is_object( $row ) ) {
    15071529                                $value = $row->meta_value;
    1508                                 $value = maybe_unserialize( $value );
     1530                                $value = wp_decode_value_from_db( $value, $value_type );
    15091531                                wp_cache_set( $cache_key, $value, 'site-options' );
    15101532                        } else {
    15111533                                if ( ! is_array( $notoptions ) ) {
    function get_network_option( $network_id, $option, $default_value = false ) { 
    15391561         * @param mixed  $value      Value of network option.
    15401562         * @param string $option     Option name.
    15411563         * @param int    $network_id ID of the network.
     1564         * @param string $value_type The expected data type of the value.
    15421565         */
    1543         return apply_filters( "site_option_{$option}", $value, $option, $network_id );
     1566        return apply_filters( "site_option_{$option}", $value, $option, $network_id, $value_type );
    15441567}
    15451568
    15461569/**
  • src/wp-includes/post.php

    diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php
    index 48906cd89bc8..60ea87eecddb 100644
    a b function delete_post_meta( $post_id, $meta_key, $meta_value = '' ) { 
    25002500 * Retrieves a post meta field for the given post ID.
    25012501 *
    25022502 * @since 1.5.0
     2503 * @since 6.3.0 Introduced the `$value_type` parameter.
    25032504 *
    2504  * @param int    $post_id Post ID.
    2505  * @param string $key     Optional. The meta key to retrieve. By default,
    2506  *                        returns data for all keys. Default empty.
    2507  * @param bool   $single  Optional. Whether to return a single value.
    2508  *                        This parameter has no effect if `$key` is not specified.
    2509  *                        Default false.
     2505 * @param int    $post_id    Post ID.
     2506 * @param string $key        Optional. The meta key to retrieve. By default,
     2507 *                           returns data for all keys. Default empty.
     2508 * @param bool   $single     Optional. Whether to return a single value.
     2509 *                           This parameter has no effect if `$key` is not specified.
     2510 *                           Default false.
     2511 * @param string $value_type Optional. The expected data type of the value.
    25102512 * @return mixed An array of values if `$single` is false.
    25112513 *               The value of the meta field if `$single` is true.
    25122514 *               False for an invalid `$post_id` (non-numeric, zero, or negative value).
    25132515 *               An empty string if a valid but non-existing post ID is passed.
    25142516 */
    2515 function get_post_meta( $post_id, $key = '', $single = false ) {
    2516         return get_metadata( 'post', $post_id, $key, $single );
     2517function get_post_meta( $post_id, $key = '', $single = false, $value_type = '' ) {
     2518        return get_metadata( 'post', $post_id, $key, $single, $value_type );
    25172519}
    25182520
    25192521/**
  • src/wp-includes/taxonomy.php

    diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php
    index 35031e3befec..b080e2c116fc 100644
    a b function delete_term_meta( $term_id, $meta_key, $meta_value = '' ) { 
    13711371 * Retrieves metadata for a term.
    13721372 *
    13731373 * @since 4.4.0
     1374 * @since 6.3.0 Introduced the `$value_type` parameter.
    13741375 *
    1375  * @param int    $term_id Term ID.
    1376  * @param string $key     Optional. The meta key to retrieve. By default,
    1377  *                        returns data for all keys. Default empty.
    1378  * @param bool   $single  Optional. Whether to return a single value.
    1379  *                        This parameter has no effect if `$key` is not specified.
    1380  *                        Default false.
     1376 * @param int    $term_id    Term ID.
     1377 * @param string $key        Optional. The meta key to retrieve. By default,
     1378 *                           returns data for all keys. Default empty.
     1379 * @param bool   $single     Optional. Whether to return a single value.
     1380 *                           This parameter has no effect if `$key` is not specified.
     1381 *                           Default false.
     1382 * @param string $value_type Optional. The expected data type of the value.
    13811383 * @return mixed An array of values if `$single` is false.
    13821384 *               The value of the meta field if `$single` is true.
    13831385 *               False for an invalid `$term_id` (non-numeric, zero, or negative value).
    13841386 *               An empty string if a valid but non-existing term ID is passed.
    13851387 */
    1386 function get_term_meta( $term_id, $key = '', $single = false ) {
    1387         return get_metadata( 'term', $term_id, $key, $single );
     1388function get_term_meta( $term_id, $key = '', $single = false, $value_type = '' ) {
     1389        return get_metadata( 'term', $term_id, $key, $single, $value_type );
    13881390}
    13891391
    13901392/**
  • src/wp-includes/user.php

    diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php
    index 8e230708e4ee..2cc6d7884bbe 100644
    a b function delete_user_meta( $user_id, $meta_key, $meta_value = '' ) { 
    11521152 * Retrieves user meta field for a user.
    11531153 *
    11541154 * @since 3.0.0
     1155 * @since 6.3.0 Introduced the `$value_type` parameter.
    11551156 *
    11561157 * @link https://developer.wordpress.org/reference/functions/get_user_meta/
    11571158 *
    1158  * @param int    $user_id User ID.
    1159  * @param string $key     Optional. The meta key to retrieve. By default,
    1160  *                        returns data for all keys.
    1161  * @param bool   $single  Optional. Whether to return a single value.
    1162  *                        This parameter has no effect if `$key` is not specified.
    1163  *                        Default false.
     1159 * @param int    $user_id    User ID.
     1160 * @param string $key        Optional. The meta key to retrieve. By default,
     1161 *                           returns data for all keys.
     1162 * @param bool   $single     Optional. Whether to return a single value.
     1163 *                           This parameter has no effect if `$key` is not specified.
     1164 *                           Default false.
     1165 * @param string $value_type Optional. The expected data type of the value.
    11641166 * @return mixed An array of values if `$single` is false.
    11651167 *               The value of meta data field if `$single` is true.
    11661168 *               False for an invalid `$user_id` (non-numeric, zero, or negative value).
    11671169 *               An empty string if a valid but non-existing user ID is passed.
    11681170 */
    1169 function get_user_meta( $user_id, $key = '', $single = false ) {
    1170         return get_metadata( 'user', $user_id, $key, $single );
     1171function get_user_meta( $user_id, $key = '', $single = false, $value_type = '' ) {
     1172        return get_metadata( 'user', $user_id, $key, $single, $value_type );
    11711173}
    11721174
    11731175/**
  • tests/phpunit/tests/functions.php

    diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php
    index 32fa2bd1e64a..c87e6b88c76a 100644
    a b public function test_wp_recursive_ksort() { 
    21502150                );
    21512151                $this->assertSameSetsWithIndex( $theme_json, $expected_theme_json );
    21522152        }
    2153 
    21542153}
  • new file tests/phpunit/tests/functions/wpDecodeValueFromDb.php

    diff --git a/tests/phpunit/tests/functions/wpDecodeValueFromDb.php b/tests/phpunit/tests/functions/wpDecodeValueFromDb.php
    new file mode 100644
    index 000000000000..d16ae3a07d8b
    - +  
     1<?php
     2
     3/**
     4 * Tests for wp_decode_value_from_db().
     5 *
     6 * @since 6.3.0
     7 *
     8 * @group functions.php
     9 * @group meta
     10 * @group option
     11 *
     12 * @ticket 55942
     13 *
     14 * @covers ::wp_decode_value_from_db
     15 */
     16class Tests_Functions_WpDecodeValueFromDb extends WP_UnitTestCase {
     17
     18        /**
     19         * Tests that wp_decode_value_from_db() returns the correct value.
     20         *
     21         * @dataProvider data_wp_decode_value_from_db
     22         *
     23         * @param mixed  $value      The value to decode.
     24         * @param string $value_type The type of the value.
     25         * @param mixed  $expected   The expected decoded value.
     26         */
     27        public function test_wp_decode_value_from_db( $value, $value_type, $expected ) {
     28                $this->assertSame( $expected, wp_decode_value_from_db( $value, $value_type ) );
     29        }
     30
     31        /**
     32         * Data provider.
     33         *
     34         * @return array
     35         */
     36        public function data_wp_decode_value_from_db() {
     37                $boolean = array(
     38                        'boolean "1"'      => array( '1', 'boolean', true ),
     39                        'boolean true'     => array( true, 'boolean', true ),
     40                        'boolean "string"' => array( 'string', 'boolean', true ),
     41                        'boolean "0"'      => array( '0', 'boolean', false ),
     42                        'boolean ""'       => array( '', 'boolean', false ),
     43                        'boolean false'    => array( false, 'boolean', false ),
     44                );
     45
     46                $integer = array(
     47                        'integer 42'   => array( 42, 'integer', 42 ),
     48                        'integer "42"' => array( '42', 'integer', 42 ),
     49                        'integer 0'    => array( 0, 'integer', 0 ),
     50                        'integer "0"'  => array( '0', 'integer', 0 ),
     51                        'integer 1'    => array( 1, 'integer', 1 ),
     52                        'integer "1"'  => array( '1', 'integer', 1 ),
     53                );
     54
     55                $float = array(
     56                        'float 12.50'   => array( 12.50, 'float', 12.50 ),
     57                        'float "12.50"' => array( '12.50', 'float', 12.50 ),
     58                        'float 0'       => array( 0, 'float', 0.0 ),
     59                        'float 1'       => array( 1, 'float', 1.0 ),
     60                );
     61
     62                $string = array(
     63                        'string "test"' => array( 'test', 'string', 'test' ),
     64                        'string 12'     => array( 12, 'string', '12' ),
     65                        'string true'   => array( true, 'string', '1' ),
     66                        'string false'  => array( false, 'string', '' ),
     67                        'string 12.435' => array( 12.435, 'string', '12.435' ),
     68                );
     69
     70                $array = array(
     71                        'serialized array'        => array( serialize( array( 'test' => 'value' ) ), 'array', array( 'test' => 'value' ) ),
     72                        'serialized object array' => array( serialize( (object) array( 'test' => 'value' ) ), 'array', array( 'test' => 'value' ) ),
     73                        'array'                   => array( array( 'test' => 'value' ), 'array', array( 'test' => 'value' ) ),
     74                        'object array'            => array( (object) array( 'test' => 'value' ), 'array', array( 'test' => 'value' ) ),
     75                );
     76
     77                return array_merge( $boolean, $integer, $float, $string, $array );
     78        }
     79
     80        /**
     81         * Tests that wp_decode_value_from_db() returns the correct value for objects.
     82         */
     83        public function test_object_wp_decode_value_from_db() {
     84                $obj       = new \stdClass();
     85                $obj->test = 'value';
     86                $this->assertEquals( $obj, wp_decode_value_from_db( serialize( $obj ), 'object' ) );
     87                $this->assertEquals( $obj, wp_decode_value_from_db( serialize( (array) $obj ), 'object' ) );
     88                $this->assertEquals( $obj, wp_decode_value_from_db( $obj, 'object' ) );
     89                $this->assertEquals( $obj, wp_decode_value_from_db( (array) $obj, 'object' ) );
     90        }
     91}