Make WordPress Core

Ticket #34738: 34738.0.diff

File 34738.0.diff, 16.0 KB (added by westonruter, 9 years ago)

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

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

    diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
    index baa50df..50ee7f2 100644
    final class WP_Customize_Manager { 
    628628        public function set_post_value( $setting_id, $value ) {
    629629                $this->unsanitized_post_values();
    630630                $this->_post_values[ $setting_id ] = $value;
     631
     632                /**
     633                 * Announce when a setting's unsanitized post value has been set.
     634                 *
     635                 * Fires when the {@see WP_Customize_Manager::set_post_value()} method is called.
     636                 *
     637                 * This is useful for <code>WP_Customize_Setting</code> instances to watch
     638                 * in order to update a cached previewed value.
     639                 *
     640                 * @since 4.4.0
     641                 *
     642                 * @param string               $setting_id Setting ID.
     643                 * @param mixed                $value      Unsanitized setting post value.
     644                 * @param WP_Customize_Manager $this       WP_Customize_Manager instance.
     645                 */
     646                do_action( 'customize_post_value_set', $setting_id, $value, $this );
     647
     648                /**
     649                 * Announce when a specific setting's unsanitized post value has been set.
     650                 *
     651                 * Fires when the {@see WP_Customize_Manager::set_post_value()} method is called.
     652                 *
     653                 * The dynamic portion of the hook name, `$setting_id`, refers to the setting ID.
     654                 *
     655                 * @since 4.4.0
     656                 *
     657                 * @param mixed                $value Unsanitized setting post value.
     658                 * @param WP_Customize_Manager $this  WP_Customize_Manager instance.
     659                 */
     660                do_action( "customize_post_value_set_{$setting_id}", $value, $this );
    631661        }
    632662
    633663        /**
  • 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 12f76d4..230fe6f 100644
    class WP_Customize_Setting { 
    8282        protected $id_data = array();
    8383
    8484        /**
     85         * Whether or not preview() was called.
     86         *
     87         * @since 4.4.0
     88         * @access protected
     89         * @var bool
     90         */
     91        protected $is_previewed = false;
     92
     93        /**
    8594         * Cache of multidimensional values to improve performance.
    8695         *
    8796         * @since 4.4.0
    class WP_Customize_Setting { 
    183192                        self::$aggregated_multidimensionals[ $this->type ] = array();
    184193                }
    185194                if ( ! isset( self::$aggregated_multidimensionals[ $this->type ][ $id_base ] ) ) {
     195                        // Only add one action per multidimensional value.
     196                        add_action( 'customize_post_value_set', array( $this, '_clear_aggregated_multidimensional_perview_applied_flag' ) );
     197
    186198                        self::$aggregated_multidimensionals[ $this->type ][ $id_base ] = array(
    187199                                'previewed_instances'       => array(), // Calling preview() will add the $setting to the array.
    188200                                'preview_applied_instances' => array(), // Flags for which settings have had their values applied.
    class WP_Customize_Setting { 
    245257                if ( ! isset( $this->_previewed_blog_id ) ) {
    246258                        $this->_previewed_blog_id = get_current_blog_id();
    247259                }
     260
     261                // Prevent re-previewing an already-previewed setting.
     262                if ( $this->is_previewed ) {
     263                        return true;
     264                }
     265
    248266                $id_base = $this->id_data['base'];
    249267                $is_multidimensional = ! empty( $this->id_data['keys'] );
    250268                $multidimensional_filter = array( $this, '_multidimensional_preview_filter' );
    class WP_Customize_Setting { 
    273291                        $needs_preview = ( $undefined === $value ); // Because the default needs to be supplied.
    274292                }
    275293
     294                // If the setting does not need previewing now, defer to when it has a value to preview.
    276295                if ( ! $needs_preview ) {
     296                        if ( ! has_action( "customize_post_value_set_{$this->id}", array( $this, 'preview' ) ) ) {
     297                                add_action( "customize_post_value_set_{$this->id}", array( $this, 'preview' ) );
     298                        }
    277299                        return false;
    278300                }
    279301
    class WP_Customize_Setting { 
    327349                                 */
    328350                                do_action( "customize_preview_{$this->type}", $this );
    329351                }
     352
     353                $this->is_previewed = true;
     354
    330355                return true;
    331356        }
    332357
    333358        /**
     359         * Clear out the previewed-applied flag for a multidimensional-aggregated value whenever its post value is updated.
     360         *
     361         * This ensures that the new value will get sanitized and used the next time
     362         * that <code>WP_Customize_Setting::_multidimensional_preview_filter()</code>
     363         * is called for this setting.
     364         *
     365         * @access private
     366         * @see WP_Customize_Manager::set_post_value()
     367         * @see WP_Customize_Setting::_multidimensional_preview_filter()
     368         *
     369         * @param string $setting_id Setting ID.
     370         */
     371        final public function _clear_aggregated_multidimensional_perview_applied_flag( $setting_id ) {
     372                if ( 0 === strpos( $setting_id, $this->id_data['base'] . '[' ) ) {
     373                        unset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['preview_applied_instances'][ $setting_id ] );
     374                }
     375        }
     376
     377        /**
    334378         * Callback function to filter non-multidimensional theme mods and options.
    335379         *
    336380         * If switch_to_blog() was called after the preview() method, and the current
    class WP_Customize_Setting { 
    369413         * the first setting previewed will be used to apply the values for the others.
    370414         *
    371415         * @since 4.4.0
    372          * @access public
     416         * @access private
    373417         *
    374418         * @see WP_Customize_Setting::$aggregated_multidimensionals
    375419         * @param mixed $original Original root value.
    376420         * @return mixed New or old value.
    377421         */
    378         public function _multidimensional_preview_filter( $original ) {
     422        final public function _multidimensional_preview_filter( $original ) {
     423                $id_base = $this->id_data['base'];
     424
    379425                if ( ! $this->is_current_blog_previewed() ) {
    380426                        return $original;
    381427                }
    382428
    383                 $id_base = $this->id_data['base'];
    384 
    385429                // If no settings have been previewed yet (which should not be the case, since $this is), just pass through the original value.
    386430                if ( empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'] ) ) {
    387431                        return $original;
    388432                }
    389433
    390434                foreach ( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'] as $previewed_setting ) {
    391                         // Skip applying previewed value for any settings that have already been applied.
    392                         if ( ! empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['preview_applied_instances'][ $previewed_setting->id ] ) ) {
    393                                 continue;
    394                         }
     435                        $previewed_setting->apply_multidimensional_preview_value();
     436                }
    395437
    396                         // Do the replacements of the posted/default sub value into the root value.
    397                         $value = $previewed_setting->post_value( $previewed_setting->default );
    398                         $root = self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['root_value'];
    399                         $root = $previewed_setting->multidimensional_replace( $root, $previewed_setting->id_data['keys'], $value );
    400                         self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['root_value'] = $root;
     438                return self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
     439        }
    401440
    402                         // Mark this setting having been applied so that it will be skipped when the filter is called again.
    403                         self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['preview_applied_instances'][ $previewed_setting->id ] = true;
     441        /**
     442         * Ensure that a multidimensional setting's post value is applied to preview.
     443         *
     444         * @since 4.4.0
     445         * @access private
     446         *
     447         * @see WP_Customize_Setting::_multidimensional_preview_filter()
     448         */
     449        final protected function apply_multidimensional_preview_value() {
     450                $id_base = $this->id_data['base'];
     451
     452                // Skip applying previewed value for any settings that have already been applied.
     453                if ( ! empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['preview_applied_instances'][ $this->id ] ) ) {
     454                        return;
    404455                }
    405456
    406                 return self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
     457                // Do the replacements of the posted/default sub value into the root value.
     458                $value = $this->post_value( $this->default );
     459                $root = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
     460                $root = $this->multidimensional_replace( $root, $this->id_data['keys'], $value );
     461                self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'] = $root;
     462
     463                // Mark this setting having been applied so that it will be skipped when the filter is called again.
     464                self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['preview_applied_instances'][ $this->id ] = true;
    407465        }
    408466
    409467        /**
    class WP_Customize_Setting { 
    610668                         */
    611669                        $value = apply_filters( "customize_value_{$id_base}", $value );
    612670                } else if ( $this->is_multidimensional_aggregated ) {
     671                        $undefined = new stdClass();
     672                        if ( $this->is_previewed && $undefined !== $this->post_value( $undefined ) ) {
     673                                $this->apply_multidimensional_preview_value();
     674                        }
    613675                        $root_value = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
    614676                        $value = $this->multidimensional_get( $root_value, $this->id_data['keys'], $this->default );
    615677                } else {
  • src/wp-includes/class-wp-customize-widgets.php

    diff --git src/wp-includes/class-wp-customize-widgets.php src/wp-includes/class-wp-customize-widgets.php
    index 6ee6942..7639d50 100644
    final class WP_Customize_Widgets { 
    13801380                 * in place from WP_Customize_Setting::preview() will use this value
    13811381                 * instead of the default widget instance value (an empty array).
    13821382                 */
    1383                 $this->manager->set_post_value( $setting_id, $instance );
     1383                $this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance ) );
    13841384
    13851385                // Obtain the widget control with the updated instance in place.
    13861386                ob_start();
  • src/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php

    diff --git src/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php src/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php
    index 2fa0b5c..073423e 100644
    class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting { 
    120120        public $original_nav_menu_term_id;
    121121
    122122        /**
    123          * Whether or not preview() was called.
    124          *
    125          * @since 4.3.0
    126          * @access protected
    127          * @var bool
    128          */
    129         protected $is_previewed = false;
    130 
    131         /**
    132123         * Whether or not update() was called.
    133124         *
    134125         * @since 4.3.0
  • src/wp-includes/customize/class-wp-customize-nav-menu-setting.php

    diff --git src/wp-includes/customize/class-wp-customize-nav-menu-setting.php src/wp-includes/customize/class-wp-customize-nav-menu-setting.php
    index 766099e..5562a8d 100644
    class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting { 
    8989        public $previous_term_id;
    9090
    9191        /**
    92          * Whether or not preview() was called.
    93          *
    94          * @since 4.3.0
    95          * @access protected
    96          * @var bool
    97          */
    98         protected $is_previewed = false;
    99 
    100         /**
    10192         * Whether or not update() was called.
    10293         *
    10394         * @since 4.3.0
  • tests/phpunit/tests/customize/setting.php

    diff --git tests/phpunit/tests/customize/setting.php tests/phpunit/tests/customize/setting.php
    index da789b1..939a7ff 100644
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    160160                $_POST['customized'] = wp_slash( wp_json_encode( $this->post_data_overrides ) );
    161161
    162162                foreach ( $this->standard_type_configs as $type => $type_options ) {
    163                         // Multidimensional: See what effect the preview filter has on a non-existent setting (default value should be seen)
     163                        // Multidimensional: See what effect the preview filter has on a non-existent setting (default value should be seen).
    164164                        $base_name = "unset_{$type}_multi";
    165165                        $name = $base_name . '[foo]';
    166166                        $default = "default_value_{$name}";
    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                         $this->assertTrue( $setting->preview() );
     170                        $this->assertTrue( $setting->preview(), $setting->id );
    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'] );
    174174
    175                         // Multidimensional: See what effect the preview has on an extant setting (default value should not be seen)
     175                        // Multidimensional: See what effect the preview has on an extant setting (default value should not be seen).
    176176                        $base_name = "set_{$type}_multi";
    177177                        $name = $base_name . '[foo]';
    178178                        $default = "default_value_{$name}";
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    184184                        $this->assertEquals( $initial_value, $base_value['foo'] );
    185185                        $this->assertEquals( $initial_value, $setting->value() );
    186186                        $setting->preview();
    187                         $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
    188                         $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     187                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // Only applicable for custom types (not options or theme_mods).
     188                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // Only applicable for custom types (not options or theme_mods).
    189189                        $base_value = call_user_func( $type_options['getter'], $base_name, array() );
    190190                        $this->assertEquals( $initial_value, $base_value['foo'] );
    191191                        $this->assertEquals( $initial_value, $setting->value() );
    192192
    193                         // Multidimensional: Test unset setting being overridden by a post value
     193                        // Multidimensional: Test unset setting being overridden by a post value.
    194194                        $base_name = "unset_{$type}_multi_overridden";
    195195                        $name = $base_name . '[foo]';
    196196                        $default = "default_value_{$name}";
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    198198                        $this->assertEquals( $this->undefined, call_user_func( $type_options['getter'], $base_name, $this->undefined ) );
    199199                        $this->assertEquals( $default, $setting->value() );
    200200                        $setting->preview();
    201                         $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
    202                         $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     201                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // Only applicable for custom types (not options or theme_mods).
     202                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // Only applicable for custom types (not options or theme_mods).
    203203                        $base_value = call_user_func( $type_options['getter'], $base_name, $this->undefined );
    204204                        $this->assertArrayHasKey( 'foo', $base_value );
    205205                        $this->assertEquals( $this->post_data_overrides[ $name ], $base_value['foo'] );
    206206
    207                         // Multidimemsional: Test set setting being overridden by a post value
     207                        // Multidimensional: Test set setting being overridden by a post value.
    208208                        $base_name = "set_{$type}_multi_overridden";
    209209                        $name = $base_name . '[foo]';
    210210                        $default = "default_value_{$name}";
    class Tests_WP_Customize_Setting extends WP_UnitTestCase { 
    221221                        $this->assertEquals( $base_initial_value['bar'], $getter['bar'] );
    222222                        $this->assertEquals( $initial_value, $setting->value() );
    223223                        $setting->preview();
    224                         $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
    225                         $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     224                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // Only applicable for custom types (not options or theme_mods).
     225                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // Only applicable for custom types (not options or theme_mods).
    226226                        $base_value = call_user_func( $type_options['getter'], $base_name, $this->undefined );
    227227                        $this->assertArrayHasKey( 'foo', $base_value );
    228228                        $this->assertEquals( $this->post_data_overrides[ $name ], $base_value['foo'] );