WordPress.org

Make WordPress Core

Ticket #32103: 32103.diff

File 32103.diff, 12.1 KB (added by westonruter, 5 years ago)

https://github.com/xwp/wordpress-develop/pull/124

  • src/wp-includes/class-wp-customize-setting.php

    diff --git src/wp-includes/class-wp-customize-setting.php src/wp-includes/class-wp-customize-setting.php
    index 98f37f9..637940b 100644
    class WP_Customize_Setting { 
    153153        protected $_original_value;
    154154
    155155        /**
    156          * Set up filters for the setting so that the preview request
    157          * will render the drafted changes.
     156         * Add filters to supply the setting's value when accessed.
     157         *
     158         * If the setting already has a pre-existing value and there is no incoming
     159         * post value for the setting, then this method will short-circuit since
     160         * there is no change to preview.
    158161         *
    159162         * @since 3.4.0
     163         * @since 4.4.0 Added boolean return value.
     164         * @access public
     165         *
     166         * @return bool False when preview short-circuits due no change needing to be previewed.
    160167         */
    161168        public function preview() {
    162                 if ( ! isset( $this->_original_value ) ) {
    163                         $this->_original_value = $this->value();
    164                 }
    165169                if ( ! isset( $this->_previewed_blog_id ) ) {
    166170                        $this->_previewed_blog_id = get_current_blog_id();
    167171                }
    168172
     173                /*
     174                 * Check if the setting has a pre-existing value (an isset check),
     175                 * and if doesn't have any incoming post value. If both checks are true,
     176                 * then the preview short-circuits because there is nothing that needs
     177                 * to be previewed.
     178                 */
     179                $undefined = new stdClass();
     180                $default = $this->default;
     181                $this->default = $undefined; // Temporarily set default to undefined so we can detect if existing value is set.
     182                $value = $this->value();
     183                $this->default = $default;
     184                $isset = ( $undefined !== $value );
     185                if ( $isset && $undefined === $this->post_value( $undefined ) ) {
     186                        return false;
     187                }
     188
     189                $this->_original_value = ( $isset ? $value : $default );
    169190                switch( $this->type ) {
    170191                        case 'theme_mod' :
    171192                                add_filter( 'theme_mod_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) );
    class WP_Customize_Setting { 
    204225                                 */
    205226                                do_action( "customize_preview_{$this->type}", $this );
    206227                }
     228                return true;
    207229        }
    208230
    209231        /**
    class WP_Customize_Setting { 
    224246                        return $original;
    225247                }
    226248
    227                 $undefined = new stdClass(); // symbol hack
    228                 $post_value = $this->post_value( $undefined );
    229                 if ( $undefined === $post_value ) {
    230                         $value = $this->_original_value;
     249                $value = $this->post_value( $this->default );
     250
     251                if ( empty( $this->id_data['keys'] ) ) {
     252                        return $value;
    231253                } else {
    232                         $value = $post_value;
     254                        return $this->multidimensional_replace( $original, $this->id_data['keys'], $value );
    233255                }
    234 
    235                 return $this->multidimensional_replace( $original, $this->id_data['keys'], $value );
    236256        }
    237257
    238258        /**
    class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting { 
    9841004         * Handle previewing the setting.
    9851005         *
    9861006         * @since 4.3.0
     1007         * @since 4.4.0 Added boolean return value.
    9871008         * @access public
    9881009         *
    9891010         * @see WP_Customize_Manager::post_value()
     1011         *
     1012         * @return bool False if method short-circuited due to no-op.
    9901013         */
    9911014        public function preview() {
    9921015                if ( $this->is_previewed ) {
    993                         return;
     1016                        return false;
     1017                }
     1018
     1019                $undefined = new stdClass();
     1020                $is_placeholder = ( $this->post_id < 0 );
     1021                $is_dirty = ( $undefined !== $this->post_value( $undefined ) );
     1022                if ( ! $is_placeholder && ! $is_dirty ) {
     1023                        return false;
    9941024                }
    9951025
    9961026                $this->is_previewed              = true;
    class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting { 
    10061036                }
    10071037
    10081038                // @todo Add get_post_metadata filters for plugins to add their data.
     1039
     1040                return true;
    10091041        }
    10101042
    10111043        /**
    class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting { 
    16181650         * Handle previewing the setting.
    16191651         *
    16201652         * @since 4.3.0
     1653         * @since 4.4.0 Added boolean return value
    16211654         * @access public
    16221655         *
    16231656         * @see WP_Customize_Manager::post_value()
     1657         *
     1658         * @return bool False if method short-circuited due to no-op.
    16241659         */
    16251660        public function preview() {
    16261661                if ( $this->is_previewed ) {
    1627                         return;
     1662                        return false;
     1663                }
     1664
     1665                $undefined = new stdClass();
     1666                $is_placeholder = ( $this->term_id < 0 );
     1667                $is_dirty = ( $undefined !== $this->post_value( $undefined ) );
     1668                if ( ! $is_placeholder && ! $is_dirty ) {
     1669                        return false;
    16281670                }
    16291671
    16301672                $this->is_previewed       = true;
    class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting { 
    16351677                add_filter( 'wp_get_nav_menu_object', array( $this, 'filter_wp_get_nav_menu_object' ), 10, 2 );
    16361678                add_filter( 'default_option_nav_menu_options', array( $this, 'filter_nav_menu_options' ) );
    16371679                add_filter( 'option_nav_menu_options', array( $this, 'filter_nav_menu_options' ) );
     1680
     1681                return true;
    16381682        }
    16391683
    16401684        /**
  • tests/phpunit/tests/customize/setting.php

    diff --git tests/phpunit/tests/customize/setting.php tests/phpunit/tests/customize/setting.php
    index 08bbc65..f3accbb 100644
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    102102                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
    103103                        $this->assertEquals( $this->undefined, call_user_func( $type_options['getter'], $name, $this->undefined ) );
    104104                        $this->assertEquals( $default, $setting->value() );
    105                         $setting->preview();
     105                        $this->assertTrue( $setting->preview(), 'Preview should not no-op since setting has no existing value.' );
    106106                        $this->assertEquals( $default, call_user_func( $type_options['getter'], $name, $this->undefined ), sprintf( 'Expected %s(%s) to return setting default: %s.', $type_options['getter'], $name, $default ) );
    107107                        $this->assertEquals( $default, $setting->value() );
    108108
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    114114                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
    115115                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name ) );
    116116                        $this->assertEquals( $initial_value, $setting->value() );
    117                         $setting->preview();
     117                        $this->assertFalse( $setting->preview(), 'Preview should no-op since setting value was extant and no post value was present.' );
    118118                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
    119119                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
    120120                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name ) );
    121121                        $this->assertEquals( $initial_value, $setting->value() );
    122122
    123                         // @todo What if we call the setter after preview() is called? If no post_value, should the new set value be stored? If that happens, then the following 3 assertions should be inverted
    124123                        $overridden_value = "overridden_value_$name";
    125124                        call_user_func( $type_options['setter'], $name, $overridden_value );
    126                         $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name ) );
    127                         $this->assertEquals( $initial_value, $setting->value() );
    128                         $this->assertNotEquals( $overridden_value, $setting->value() );
     125                        $message = 'Initial value should be overridden because initial preview() was no-op due to setting having existing value and/or post value was absent.';
     126                        $this->assertEquals( $overridden_value, call_user_func( $type_options['getter'], $name ), $message );
     127                        $this->assertEquals( $overridden_value, $setting->value(), $message );
     128                        $this->assertNotEquals( $initial_value, $setting->value(), $message );
    129129
    130130                        // Non-multidimensional: Test unset setting being overridden by a post value
    131131                        $name = "unset_{$type}_overridden";
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    133133                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
    134134                        $this->assertEquals( $this->undefined, call_user_func( $type_options['getter'], $name, $this->undefined ) );
    135135                        $this->assertEquals( $default, $setting->value() );
    136                         $setting->preview(); // activate post_data
     136                        $this->assertTrue( $setting->preview(), 'Preview applies because setting has post_data_overrides.' ); // activate post_data
    137137                        $this->assertEquals( $this->post_data_overrides[ $name ], call_user_func( $type_options['getter'], $name, $this->undefined ) );
    138138                        $this->assertEquals( $this->post_data_overrides[ $name ], $setting->value() );
    139139
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    145145                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
    146146                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name, $this->undefined ) );
    147147                        $this->assertEquals( $initial_value, $setting->value() );
    148                         $setting->preview(); // activate post_data
     148                        $this->assertTrue( $setting->preview(), 'Preview applies because setting has post_data_overrides.' ); // activate post_data
    149149                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
    150150                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
    151151                        $this->assertEquals( $this->post_data_overrides[ $name ], call_user_func( $type_options['getter'], $name, $this->undefined ) );
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    167167                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
    168168                        $this->assertEquals( $this->undefined, call_user_func( $type_options['getter'], $base_name, $this->undefined ) );
    169169                        $this->assertEquals( $default, $setting->value() );
    170                         $setting->preview();
     170                        $this->assertTrue( $setting->preview() );
    171171                        $base_value = call_user_func( $type_options['getter'], $base_name, $this->undefined );
    172172                        $this->assertArrayHasKey( 'foo', $base_value );
    173173                        $this->assertEquals( $default, $base_value['foo'] );
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    311311                $this->assertEquals( $initial_value, $this->custom_type_getter( $name, $this->undefined ) );
    312312                $this->assertEquals( $initial_value, $setting->value() );
    313313                $setting->preview();
    314                 $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
    315                 $this->assertEquals( 2, did_action( "customize_preview_{$setting->type}" ) );
     314                $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ), 'Zero preview actions because initial value is set with no incoming post value, so there is no preview to apply.' );
     315                $this->assertEquals( 1, did_action( "customize_preview_{$setting->type}" ) );
    316316                $this->assertEquals( $initial_value, $this->custom_type_getter( $name, $this->undefined ) ); // should be same as above
    317317                $this->assertEquals( $initial_value, $setting->value() ); // should be same as above
    318318
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    325325                $this->assertEquals( $this->undefined, $this->custom_type_getter( $name, $this->undefined ) );
    326326                $this->assertEquals( $default, $setting->value() );
    327327                $setting->preview();
    328                 $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
    329                 $this->assertEquals( 3, did_action( "customize_preview_{$setting->type}" ) );
     328                $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ), 'One preview action now because initial value was not set and/or there is no incoming post value, so there is is a preview to apply.' );
     329                $this->assertEquals( 2, did_action( "customize_preview_{$setting->type}" ) );
    330330                $this->assertEquals( $post_data_overrides[ $name ], $this->custom_type_getter( $name, $this->undefined ) );
    331331                $this->assertEquals( $post_data_overrides[ $name ], $setting->value() );
    332332
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    342342                $this->assertEquals( $initial_value, $setting->value() );
    343343                $setting->preview();
    344344                $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
    345                 $this->assertEquals( 4, did_action( "customize_preview_{$setting->type}" ) );
     345                $this->assertEquals( 3, did_action( "customize_preview_{$setting->type}" ) );
    346346                $this->assertEquals( $post_data_overrides[ $name ], $this->custom_type_getter( $name, $this->undefined ) );
    347347                $this->assertEquals( $post_data_overrides[ $name ], $setting->value() );
    348348