WordPress.org

Make WordPress Core

Ticket #22192: 22192.5.diff

File 22192.5.diff, 4.2 KB (added by boonebgorges, 7 years ago)
  • src/wp-includes/option.php

    diff --git src/wp-includes/option.php src/wp-includes/option.php
    index 6134606..4adcbe7 100644
    function update_option( $option, $value ) { 
    264264         */
    265265        $value = apply_filters( 'pre_update_option', $value, $option, $old_value );
    266266
    267         // If the new and old values are the same, no need to update.
    268         if ( $value === $old_value )
     267        /*
     268         * If the new and old values are the same, no need to update.
     269         * Scalar values in the cache will always be strings, so we must compare string values.
     270         */
     271        $values = array(
     272                'old' => $old_value,
     273                'new' => $value,
     274        );
     275
     276        foreach ( $values as $_key => &$_value ) {
     277                // Special handling for false-ish values.
     278                if ( false === $_value ) {
     279                        $_value = '0';
     280
     281                // Empty strings in the database should be seen as equivalent to false-ish cache values.
     282                } elseif ( 'old' === $_key && '' === $_value ) {
     283                        $_value = '0';
     284
     285                // Cast scalars to a string so type discrepancies don't result in cache misses.
     286                } elseif ( is_scalar( $_value ) ) {
     287                        $_value = (string) $_value;
     288                }
     289        }
     290
     291        if ( $values['old'] === $values['new'] ) {
    269292                return false;
     293        }
    270294
    271295        if ( false === $old_value )
    272296                return add_option( $option, $value );
  • tests/phpunit/tests/option/option.php

    diff --git tests/phpunit/tests/option/option.php tests/phpunit/tests/option/option.php
    index a866cea..8fc666b 100644
    class Tests_Option_Option extends WP_UnitTestCase { 
    9999        function test_special_option_name_notoptions() {
    100100                delete_option( 'notoptions' );
    101101        }
     102
     103        /**
     104         * @ticket 22192
     105         */
     106        public function test_add_option_with_value_of_false_should_store_false_in_the_cache() {
     107                add_option( 'foo', false );
     108                $a = wp_cache_get( 'alloptions', 'options' );
     109                $this->assertSame( false, $a['foo'] );
     110        }
     111
     112        /**
     113         * @ticket 22192
     114         */
     115        public function test_add_option_with_value_of_false_should_store_empty_string_in_the_database() {
     116                add_option( 'foo', false );
     117
     118                // Delete cache to ensure we pull from the database.
     119                wp_cache_delete( 'alloptions', 'options' );
     120
     121                $this->assertSame( '', get_option( 'foo' ) );
     122        }
     123
     124        /**
     125         * @ticket 22192
     126         * @dataProvider data_update_option_type_juggling
     127         */
     128        public function test_update_option_should_hit_cache_when_loosely_equal_to_existing_value_and_cached_values_are_faithful_to_original_type( $old_value, $new_value ) {
     129                global $wpdb;
     130
     131                add_option( 'foo', $old_value );
     132                $num_queries = $wpdb->num_queries;
     133
     134                $updated = update_option( 'foo', $new_value );
     135
     136                $this->assertFalse( $updated );
     137                $this->assertSame( $num_queries, $wpdb->num_queries );
     138        }
     139
     140        /**
     141         * @ticket 22192
     142         * @dataProvider data_update_option_type_juggling
     143         */
     144        public function test_update_option_should_hit_cache_when_loosely_equal_to_existing_value_and_cached_values_are_pulled_from_the_database( $old_value, $new_value ) {
     145                global $wpdb;
     146
     147                add_option( 'foo', $old_value );
     148                wp_cache_delete( 'alloptions', 'options' );
     149                wp_load_alloptions();
     150
     151                $num_queries = $wpdb->num_queries;
     152
     153                $updated = update_option( 'foo', $new_value );
     154
     155                $this->assertFalse( $updated );
     156                $this->assertSame( $num_queries, $wpdb->num_queries );
     157        }
     158
     159        public function data_update_option_type_juggling() {
     160                return array(
     161                        // Truthy
     162                        array( '1', '1' ),
     163                        array( '1', intval( 1 ) ),
     164                        array( '1', floatval( 1 ) ),
     165                        array( '1', true ),
     166                        array( 1, '1' ),
     167                        array( 1, intval( 1 ) ),
     168                        array( 1, floatval( 1 ) ),
     169                        array( 1, true ),
     170                        array( floatval( 1 ), '1' ),
     171                        array( floatval( 1 ), intval( 1 ) ),
     172                        array( floatval( 1 ), floatval( 1 ) ),
     173                        array( floatval( 1 ), true ),
     174                        array( true, '1' ),
     175                        array( true, intval( 1 ) ),
     176                        array( true, floatval( 1 ) ),
     177                        array( true, true ),
     178
     179                        // Falsey
     180                        array( '0', '0' ),
     181                        array( '0', intval( 0 ) ),
     182                        array( '0', floatval( 0 ) ),
     183                        array( '0', false ),
     184                        array( 0, '0' ),
     185                        array( 0, intval( 0 ) ),
     186                        array( 0, floatval( 0 ) ),
     187                        array( 0, false ),
     188                        array( floatval( 0 ), '0' ),
     189                        array( floatval( 0 ), intval( 0 ) ),
     190                        array( floatval( 0 ), floatval( 0 ) ),
     191                        array( floatval( 0 ), false ),
     192                        array( false, '0' ),
     193                        array( false, intval( 0 ) ),
     194                        array( false, floatval( 0 ) ),
     195                        array( false, false ),
     196                );
     197        }
    102198}