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/tests/phpunit/tests/option/option.php

    r56796 r56946  
    371371
    372372    /**
    373      * Tests that update_option() triggers one additional query and returns true
    374      * for some loosely equal old and new values when the old value is retrieved from the cache.
    375      *
    376      * The additional query is triggered to update the value in the database.
    377      *
    378      * @ticket 22192
    379      *
    380      * @covers ::update_option
    381      *
    382      * @dataProvider data_loosely_equal_values_that_should_update
    383      *
    384      * @param mixed $old_value The old value.
    385      * @param mixed $new_value The new value to try to set.
    386      */
    387     public function test_update_option_should_update_some_loosely_equal_values_from_cache( $old_value, $new_value ) {
    388         add_option( 'foo', $old_value );
    389 
    390         $num_queries = get_num_queries();
    391 
    392         // Comparison will happen against value cached during add_option() above.
    393         $updated = update_option( 'foo', $new_value );
    394 
    395         $this->assertSame( 1, get_num_queries() - $num_queries, 'One additional query should have run to update the value.' );
    396         $this->assertTrue( $updated, 'update_option() should have returned true.' );
    397     }
    398 
    399     /**
    400      * Tests that update_option() triggers two additional queries and returns true
    401      * for some loosely equal old and new values when the old value is retrieved from the database.
    402      *
    403      * The two additional queries are triggered to:
    404      * 1. retrieve the old value from the database, as the option does not exist in the cache.
    405      * 2. update the value in the database.
    406      *
    407      * @ticket 22192
    408      *
    409      * @covers ::update_option
    410      *
    411      * @dataProvider data_loosely_equal_values_that_should_update
    412      *
    413      * @param mixed $old_value The old value.
    414      * @param mixed $new_value The new value to try to set.
    415      */
    416     public function test_update_option_should_update_some_loosely_equal_values_from_db( $old_value, $new_value ) {
    417         add_option( 'foo', $old_value );
    418 
    419         $num_queries = get_num_queries();
    420 
    421         // Delete cache.
    422         wp_cache_delete( 'alloptions', 'options' );
    423         $updated = update_option( 'foo', $new_value );
    424 
    425         $this->assertSame( 2, get_num_queries() - $num_queries, 'Two additional queries should have run.' );
    426         $this->assertTrue( $updated, 'update_option() should have returned true.' );
    427     }
    428 
    429     /**
    430      * Tests that update_option() triggers one additional query and returns true
    431      * for some loosely equal old and new values when the old value is retrieved from a refreshed cache.
    432      *
    433      * The additional query is triggered to update the value in the database.
    434      *
    435      * @ticket 22192
    436      *
    437      * @covers ::update_option
    438      *
    439      * @dataProvider data_loosely_equal_values_that_should_update
    440      *
    441      * @param mixed $old_value The old value.
    442      * @param mixed $new_value The new value to try to set.
    443      */
    444     public function test_update_option_should_update_some_loosely_equal_values_from_refreshed_cache( $old_value, $new_value ) {
    445         add_option( 'foo', $old_value );
    446 
    447         // Delete and refresh cache from DB.
    448         wp_cache_delete( 'alloptions', 'options' );
    449         wp_load_alloptions();
    450 
    451         $num_queries = get_num_queries();
    452         $updated     = update_option( 'foo', $new_value );
    453 
    454         $this->assertSame( 1, get_num_queries() - $num_queries, 'One additional query should have run to update the value.' );
    455         $this->assertTrue( $updated, 'update_option() should have returned true.' );
    456     }
    457 
    458     /**
    459      * Data provider.
    460      *
    461      * @return array
    462      */
    463     public function data_loosely_equal_values_that_should_update() {
    464         return array(
    465             // Falsey values.
    466             '(string) "0" to false'       => array( '0', false ),
    467             'empty string to (int) 0'     => array( '', 0 ),
    468             'empty string to (float) 0.0' => array( '', 0.0 ),
    469             '(int) 0 to empty string'     => array( 0, '' ),
    470             '(int) 0 to false'            => array( 0, false ),
    471             '(float) 0.0 to empty string' => array( 0.0, '' ),
    472             '(float) 0.0 to false'        => array( 0.0, false ),
    473             'false to (string) "0"'       => array( false, '0' ),
    474             'false to (int) 0'            => array( false, 0 ),
    475             'false to (float) 0.0'        => array( false, 0.0 ),
    476 
    477             // Non-scalar values.
    478             'false to array()'            => array( false, array() ),
    479             '(string) "false" to array()' => array( 'false', array() ),
    480             'empty string to array()'     => array( '', array() ),
    481             '(int 0) to array()'          => array( 0, array() ),
    482             '(string) "0" to array()'     => array( '0', array() ),
    483             '(string) "false" to null'    => array( 'false', null ),
    484             '(int) 0 to null'             => array( 0, null ),
    485             '(string) "0" to null'        => array( '0', null ),
    486             'array() to false'            => array( array(), false ),
    487             'array() to (string) "false"' => array( array(), 'false' ),
    488             'array() to empty string'     => array( array(), '' ),
    489             'array() to (int) 0'          => array( array(), 0 ),
    490             'array() to (string) "0"'     => array( array(), '0' ),
    491             'array() to null'             => array( array(), null ),
    492         );
    493     }
    494 
    495     /**
    496      * Tests that update_option() triggers no additional queries and returns false
    497      * for some values when the old value is retrieved from the cache.
    498      *
    499      * @ticket 22192
    500      *
    501      * @covers ::update_option
    502      *
    503      * @dataProvider data_loosely_equal_values_that_should_not_update
    504      * @dataProvider data_strictly_equal_values
    505      *
    506      * @param mixed $old_value The old value.
    507      * @param mixed $new_value The new value to try to set.
    508      */
    509     public function test_update_option_should_not_update_some_values_from_cache( $old_value, $new_value ) {
    510         add_option( 'foo', $old_value );
    511 
    512         $num_queries = get_num_queries();
    513 
    514         // Comparison will happen against value cached during add_option() above.
    515         $updated = update_option( 'foo', $new_value );
    516 
    517         $this->assertSame( $num_queries, get_num_queries(), 'No additional queries should have run.' );
    518         $this->assertFalse( $updated, 'update_option() should have returned false.' );
    519     }
    520 
    521     /**
    522      * Tests that update_option() triggers one additional query and returns false
    523      * for some values when the old value is retrieved from the database.
    524      *
    525      * The additional query is triggered to retrieve the old value from the database.
    526      *
    527      * @ticket 22192
    528      *
    529      * @covers ::update_option
    530      *
    531      * @dataProvider data_loosely_equal_values_that_should_not_update
    532      * @dataProvider data_strictly_equal_values
    533      *
    534      * @param mixed $old_value The old value.
    535      * @param mixed $new_value The new value to try to set.
    536      */
    537     public function test_update_option_should_not_update_some_values_from_db( $old_value, $new_value ) {
    538         add_option( 'foo', $old_value );
    539 
    540         $num_queries = get_num_queries();
    541 
    542         // Delete cache.
    543         wp_cache_delete( 'alloptions', 'options' );
    544         $updated = update_option( 'foo', $new_value );
    545 
    546         $this->assertSame( 1, get_num_queries() - $num_queries, 'One additional query should have run.' );
    547         $this->assertFalse( $updated, 'update_option() should have returned false.' );
    548     }
    549 
    550     /**
    551      * Tests that update_option() triggers no additional queries and returns false
    552      * for some values when the old value is retrieved from a refreshed cache.
    553      *
    554      * @ticket 22192
    555      *
    556      * @covers ::update_option
    557      *
    558      * @dataProvider data_loosely_equal_values_that_should_not_update
    559      * @dataProvider data_strictly_equal_values
    560      *
    561      * @param mixed $old_value The old value.
    562      * @param mixed $new_value The new value to try to set.
    563      */
    564     public function test_update_option_should_not_update_some_values_from_refreshed_cache( $old_value, $new_value ) {
    565         add_option( 'foo', $old_value );
    566 
    567         // Delete and refresh cache from DB.
    568         wp_cache_delete( 'alloptions', 'options' );
    569         wp_load_alloptions();
    570 
    571         $num_queries = get_num_queries();
    572         $updated     = update_option( 'foo', $new_value );
    573 
    574         $this->assertSame( $num_queries, get_num_queries(), 'No additional queries should have run.' );
    575         $this->assertFalse( $updated, 'update_option() should have returned false.' );
    576     }
    577 
    578     /**
    579      * Data provider.
    580      *
    581      * @return array[]
    582      */
    583     public function data_loosely_equal_values_that_should_not_update() {
    584         return array(
    585             // Truthy values.
    586             '(string) "1" to (int) 1'     => array( '1', 1 ),
    587             '(string) "1" to (float) 1.0' => array( '1', 1.0 ),
    588             '(string) "1" to true'        => array( '1', true ),
    589             '(int) 1 to (string) "1"'     => array( 1, '1' ),
    590             '1 to (float) 1.0'            => array( 1, 1.0 ),
    591             '(int) 1 to true'             => array( 1, true ),
    592             '(float) 1.0 to (string) "1"' => array( 1.0, '1' ),
    593             '(float) 1.0 to (int) 1'      => array( 1.0, 1 ),
    594             '1.0 to true'                 => array( 1.0, true ),
    595             'true to (string) "1"'        => array( true, '1' ),
    596             'true to 1'                   => array( true, 1 ),
    597             'true to (float) 1.0'         => array( true, 1.0 ),
    598 
    599             // Falsey values.
    600             '(string) "0" to (int) 0'     => array( '0', 0 ),
    601             '(string) "0" to (float) 0.0' => array( '0', 0.0 ),
    602             '(int) 0 to (string) "0"'     => array( 0, '0' ),
    603             '(int) 0 to (float) 0.0'      => array( 0, 0.0 ),
    604             '(float) 0.0 to (string) "0"' => array( 0.0, '0' ),
    605             '(float) 0.0 to (int) 0'      => array( 0.0, 0 ),
    606             'empty string to false'       => array( '', false ),
    607             'empty string to null'        => array( '', null ),
    608 
    609             /*
    610              * null as an initial value behaves differently by triggering
    611              * a query, so it is not included in these datasets.
    612              *
    613              * See data_stored_as_empty_string() and its related test.
    614              */
    615         );
    616     }
    617 
    618     /**
    619      * Data provider.
    620      *
    621      * @return array
    622      */
    623     public function data_strictly_equal_values() {
    624         $obj = new stdClass();
    625 
    626         return array(
    627             // Truthy values.
    628             '(string) "1"'       => array( '1', '1' ),
    629             '(int) 1'            => array( 1, 1 ),
    630             '(float) 1.0'        => array( 1.0, 1.0 ),
    631             'true'               => array( true, true ),
    632             'string with spaces' => array( ' ', ' ' ),
    633             'non-empty array'    => array( array( 'false' ), array( 'false' ) ),
    634             'object'             => array( $obj, $obj ),
    635 
    636             // Falsey values.
    637             '(string) "0"'       => array( '0', '0' ),
    638             'empty string'       => array( '', '' ),
    639             '(int) 0'            => array( 0, 0 ),
    640             '(float) 0.0'        => array( 0.0, 0.0 ),
    641             'empty array'        => array( array(), array() ),
    642             'false'              => array( false, false ),
    643 
    644             /*
    645              * null is not included in these datasets because
    646              * false is the default value, which triggers
    647              * a call to add_option().
    648              *
    649              * See data_stored_as_empty_string() and its related test.
    650              */
    651         );
    652     }
    653 
    654     /**
    655      * Tests that update_option() adds a non-existent option when the new value
    656      * is stored as an empty string and false is the default value for the option.
    657      *
    658      * @ticket 22192
    659      *
    660      * @dataProvider data_stored_as_empty_string
    661      *
    662      * @param mixed $new_value A value that casts to an empty string.
    663      */
    664     public function test_update_option_should_add_option_when_the_new_value_is_stored_as_an_empty_string_and_matches_default_value_false( $new_value ) {
    665         global $wpdb;
    666 
    667         $this->assertTrue( update_option( 'foo', $new_value ), 'update_option() should have returned true.' );
    668 
    669         $actual = $wpdb->get_row( "SELECT option_value FROM $wpdb->options WHERE option_name = 'foo' LIMIT 1" );
    670 
    671         $this->assertIsObject( $actual, 'The option was not added to the database.' );
    672         $this->assertObjectHasProperty( 'option_value', $actual, 'The "option_value" property was not included.' );
    673         $this->assertSame( '', $actual->option_value, 'The value was not stored as an empty string.' );
    674     }
    675 
    676     /**
    677      * Data provider.
    678      *
    679      * @return array[]
    680      */
    681     public function data_stored_as_empty_string() {
    682         return array(
    683             'empty string' => array( '' ),
    684             'null'         => array( null ),
    685         );
    686     }
    687 
    688     /**
    689      * Tests that update_option() adds a non-existent option that uses a filtered default value.
    690      *
    691      * @ticket 22192
    692      *
    693      * @covers ::update_option
    694      */
    695     public function test_update_option_should_add_option_with_filtered_default_value() {
    696         global $wpdb;
    697 
    698         $option        = 'update_option_custom_default';
    699         $default_value = 'default-value';
    700 
    701         add_filter(
    702             "default_option_{$option}",
    703             static function () use ( $default_value ) {
    704                 return $default_value;
    705             }
    706         );
    707 
    708         /*
    709          * For a non existing option with the unfiltered default of false, passing false here wouldn't work.
    710          * Because the default is different than false here though, passing false is expected to result in
    711          * a database update.
    712          */
    713         $this->assertTrue( update_option( $option, false ), 'update_option() should have returned true.' );
    714 
    715         $actual = $wpdb->get_row(
    716             $wpdb->prepare(
    717                 "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
    718                 $option
    719             )
    720         );
    721 
    722         $this->assertIsObject( $actual, 'The option was not added to the database.' );
    723         $this->assertObjectHasProperty( 'option_value', $actual, 'The "option_value" property was not included.' );
    724         $this->assertSame( '', $actual->option_value, 'The new value was not stored in the database.' );
    725     }
    726 
    727     /**
    728      * Tests that a non-existent option is added even when its pre filter returns a value.
    729      *
    730      * @ticket 22192
    731      *
    732      * @covers ::update_option
    733      */
    734     public function test_update_option_with_pre_filter_adds_missing_option() {
    735         // Force a return value of integer 0.
    736         add_filter( 'pre_option_foo', '__return_zero' );
    737 
    738         /*
    739          * This should succeed, since the 'foo' option does not exist in the database.
    740          * The default value is false, so it differs from 0.
    741          */
    742         $this->assertTrue( update_option( 'foo', 0 ) );
    743     }
    744 
    745     /**
    746      * Tests that an existing option is updated even when its pre filter returns the same value.
    747      *
    748      * @ticket 22192
    749      *
    750      * @covers ::update_option
    751      */
    752     public function test_update_option_with_pre_filter_updates_option_with_different_value() {
    753         // Add the option with a value of 1 to the database.
    754         add_option( 'foo', 1 );
    755 
    756         // Force a return value of integer 0.
    757         add_filter( 'pre_option_foo', '__return_zero' );
    758 
    759         /*
    760          * This should succeed, since the 'foo' option has a value of 1 in the database.
    761          * Therefore it differs from 0 and should be updated.
    762          */
    763         $this->assertTrue( update_option( 'foo', 0 ) );
    764     }
    765 
    766     /**
    767      * Tests that calling update_option() does not permanently remove pre filters.
    768      *
    769      * @ticket 22192
    770      *
    771      * @covers ::update_option
    772      */
    773     public function test_update_option_maintains_pre_filters() {
    774         add_filter( 'pre_option_foo', '__return_zero' );
    775         update_option( 'foo', 0 );
    776 
    777         // Assert that the filter is still present.
    778         $this->assertSame( 10, has_filter( 'pre_option_foo', '__return_zero' ) );
    779     }
    780 
    781     /**
    782373     * Tests that calling update_option() with changed autoload from 'no' to 'yes' updates the cache correctly.
    783374     *
Note: See TracChangeset for help on using the changeset viewer.