Make WordPress Core


Ignore:
Timestamp:
10/16/2023 08:35:05 PM (14 months ago)
Author:
joemcgill
Message:

Options, Meta APIs: Revert update_option changes.

This reverts changes from [56648], [56681], [56717], [56762], [56788], [56797], and [56814] to restore the behavior for update_option() and update_network_option() to their prior state as of 6.3.X due to the discovery of various backwards compatibility issues found late in the 6.4 release cycle.

Props mukesh27, costdev, flixos90, spacedmonkey, snicco, jrf, joemcgill.
See #22192, #59360.

File:
1 edited

Legend:

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

    r56817 r56946  
    778778
    779779    /*
    780      * To get the actual raw old value from the database, any existing pre filters need to be temporarily disabled.
    781      * Immediately after getting the raw value, they are reinstated.
    782      * The raw value is only used to determine whether a value is present in the database. It is not used anywhere
    783      * else, and is not passed to any of the hooks either.
    784      */
    785     if ( has_filter( "pre_option_{$option}" ) ) {
    786         global $wp_filter;
    787 
    788         $old_filters = $wp_filter[ "pre_option_{$option}" ];
    789         unset( $wp_filter[ "pre_option_{$option}" ] );
    790 
    791         $raw_old_value                       = get_option( $option );
    792         $wp_filter[ "pre_option_{$option}" ] = $old_filters;
    793     } else {
    794         $raw_old_value = $old_value;
     780     * If the new and old values are the same, no need to update.
     781     *
     782     * Unserialized values will be adequate in most cases. If the unserialized
     783     * data differs, the (maybe) serialized data is checked to avoid
     784     * unnecessary database calls for otherwise identical object instances.
     785     *
     786     * See https://core.trac.wordpress.org/ticket/38903
     787     */
     788    if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
     789        return false;
    795790    }
    796791
    797792    /** This filter is documented in wp-includes/option.php */
    798     $default_value = apply_filters( "default_option_{$option}", false, $option, false );
    799 
    800     /*
    801      * If the new and old values are the same, no need to update.
    802      *
    803      * An exception applies when no value is set in the database, i.e. the old value is the default.
    804      * In that case, the new value should always be added as it may be intentional to store it rather than relying on the default.
    805      *
    806      * See https://core.trac.wordpress.org/ticket/38903 and https://core.trac.wordpress.org/ticket/22192.
    807      */
    808     if (
    809         $value === $raw_old_value ||
    810         (
    811             $raw_old_value !== $default_value &&
    812             _is_equal_database_value( $raw_old_value, $value )
    813         )
    814     ) {
    815         return false;
    816     }
    817 
    818     if ( $raw_old_value === $default_value ) {
    819 
     793    if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
    820794        // Default setting for new options is 'yes'.
    821795        if ( null === $autoload ) {
     
    21462120
    21472121    /*
    2148      * To get the actual raw old value from the database, any existing pre filters need to be temporarily disabled.
    2149      * Immediately after getting the raw value, they are reinstated.
    2150      * The raw value is only used to determine whether a value is present in the database. It is not used anywhere
    2151      * else, and is not passed to any of the hooks either.
    2152      */
    2153     global $wp_filter;
    2154 
    2155     /** This filter is documented in wp-includes/option.php */
    2156     $default_value = apply_filters( "default_site_option_{$option}", false, $option, $network_id );
    2157 
    2158     $has_site_filter   = has_filter( "pre_site_option_{$option}" );
    2159     $has_option_filter = has_filter( "pre_option_{$option}" );
    2160     if ( $has_site_filter || $has_option_filter ) {
    2161         if ( $has_site_filter ) {
    2162             $old_ms_filters = $wp_filter[ "pre_site_option_{$option}" ];
    2163             unset( $wp_filter[ "pre_site_option_{$option}" ] );
    2164         }
    2165 
    2166         if ( $has_option_filter ) {
    2167             $old_single_site_filters = $wp_filter[ "pre_option_{$option}" ];
    2168             unset( $wp_filter[ "pre_option_{$option}" ] );
    2169         }
    2170 
    2171         if ( is_multisite() ) {
    2172             $raw_old_value = get_network_option( $network_id, $option );
    2173         } else {
    2174             $raw_old_value = get_option( $option, $default_value );
    2175         }
    2176 
    2177         if ( $has_site_filter ) {
    2178             $wp_filter[ "pre_site_option_{$option}" ] = $old_ms_filters;
    2179         }
    2180         if ( $has_option_filter ) {
    2181             $wp_filter[ "pre_option_{$option}" ] = $old_single_site_filters;
    2182         }
    2183     } else {
    2184         $raw_old_value = $old_value;
    2185     }
    2186 
    2187     if ( ! is_multisite() ) {
    2188         /** This filter is documented in wp-includes/option.php */
    2189         $default_value = apply_filters( "default_option_{$option}", $default_value, $option, true );
    2190     }
    2191 
    2192     /*
    21932122     * If the new and old values are the same, no need to update.
    21942123     *
    2195      * An exception applies when no value is set in the database, i.e. the old value is the default.
    2196      * In that case, the new value should always be added as it may be intentional to store it rather than relying on the default.
    2197      *
    2198      * See https://core.trac.wordpress.org/ticket/44956 and https://core.trac.wordpress.org/ticket/22192 and https://core.trac.wordpress.org/ticket/59360
    2199      */
    2200     if (
    2201         $value === $raw_old_value ||
    2202         (
    2203             false !== $raw_old_value &&
    2204             /*
    2205              * Single site stores values in the `option_value` field, which cannot be set to NULL.
    2206              * This means a PHP `null` value will be cast to an empty string, which can be considered
    2207              * equal to values such as an empty string, or false when cast to string.
    2208              *
    2209              * However, Multisite stores values in the `meta_value` field, which can be set to NULL.
    2210              * As NULL is unique in the database, skip checking an old or new value of NULL
    2211              * against any other value.
    2212              */
    2213             ( ! is_multisite() || ! ( null === $raw_old_value || null === $value ) ) &&
    2214             _is_equal_database_value( $raw_old_value, $value )
    2215         )
    2216     ) {
     2124     * Unserialized values will be adequate in most cases. If the unserialized
     2125     * data differs, the (maybe) serialized data is checked to avoid
     2126     * unnecessary database calls for otherwise identical object instances.
     2127     *
     2128     * See https://core.trac.wordpress.org/ticket/44956
     2129     */
     2130    if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
    22172131        return false;
    22182132    }
    22192133
    2220     if ( $default_value === $raw_old_value ) {
     2134    if ( false === $old_value ) {
    22212135        return add_network_option( $network_id, $option, $value );
    22222136    }
     
    29962910    return $registered[ $option ]['default'];
    29972911}
    2998 
    2999 /**
    3000  * Determines whether two values will be equal when stored in the database.
    3001  *
    3002  * @since 6.4.0
    3003  * @access private
    3004  *
    3005  * @param mixed $old_value The old value to compare.
    3006  * @param mixed $new_value The new value to compare.
    3007  * @return bool True if the values are equal, false otherwise.
    3008  */
    3009 function _is_equal_database_value( $old_value, $new_value ) {
    3010     $values = array(
    3011         'old' => $old_value,
    3012         'new' => $new_value,
    3013     );
    3014 
    3015     foreach ( $values as $_key => &$_value ) {
    3016         // Cast scalars or null to a string so type discrepancies don't result in cache misses.
    3017         if ( null === $_value || is_scalar( $_value ) ) {
    3018             $_value = (string) $_value;
    3019         }
    3020     }
    3021 
    3022     if ( $values['old'] === $values['new'] ) {
    3023         return true;
    3024     }
    3025 
    3026     /*
    3027      * Unserialized values will be adequate in most cases. If the unserialized
    3028      * data differs, the (maybe) serialized data is checked to avoid
    3029      * unnecessary database calls for otherwise identical object instances.
    3030      *
    3031      * See https://core.trac.wordpress.org/ticket/38903
    3032      */
    3033     return maybe_serialize( $old_value ) === maybe_serialize( $new_value );
    3034 }
Note: See TracChangeset for help on using the changeset viewer.