Make WordPress Core

Ticket #30988: 30988.2.diff

File 30988.2.diff, 22.7 KB (added by westonruter, 10 years ago)

Additional changes: https://github.com/xwp/wordpress-develop/compare/724e16d...3feec2c

  • 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 c9dc52d..7961d8d 100644
    final class WP_Customize_Manager { 
    7575         * @since 3.4.0
    7676         */
    7777        public function __construct() {
    78                 require( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
    79                 require( ABSPATH . WPINC . '/class-wp-customize-panel.php' );
    80                 require( ABSPATH . WPINC . '/class-wp-customize-section.php' );
    81                 require( ABSPATH . WPINC . '/class-wp-customize-control.php' );
    82                 require( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
     78                require_once( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
     79                require_once( ABSPATH . WPINC . '/class-wp-customize-panel.php' );
     80                require_once( ABSPATH . WPINC . '/class-wp-customize-section.php' );
     81                require_once( ABSPATH . WPINC . '/class-wp-customize-control.php' );
     82                require_once( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
    8383
    8484                $this->widgets = new WP_Customize_Widgets( $this );
    8585
    final class WP_Customize_Manager { 
    399399        }
    400400
    401401        /**
    402          * Decode the $_POST['customized'] values for a specific Customize Setting.
     402         * Decode the $_POST['customized'] values, and cache in _post_values array.
    403403         *
    404          * @since 3.4.0
    405          *
    406          * @param WP_Customize_Setting $setting A WP_Customize_Setting derived object
    407          * @return string $post_value Sanitized value
     404         * @since 4.1.1
    408405         */
    409         public function post_value( $setting ) {
     406        protected function parse_post_data() {
    410407                if ( ! isset( $this->_post_values ) ) {
    411                         if ( isset( $_POST['customized'] ) )
     408                        if ( isset( $_POST['customized'] ) ) {
    412409                                $this->_post_values = json_decode( wp_unslash( $_POST['customized'] ), true );
    413                         else
     410                        } else {
    414411                                $this->_post_values = false;
     412                        }
    415413                }
     414        }
    416415
    417                 if ( isset( $this->_post_values[ $setting->id ] ) )
     416        /**
     417         * Get the post data value for a specific Customize Setting.
     418         *
     419         * @since 3.4.0
     420         *
     421         * @param WP_Customize_Setting $setting A WP_Customize_Setting derived object
     422         * @param mixed $default Value to return when setting value is posted
     423         * @return mixed $post_value Sanitized value
     424         */
     425        public function post_value( $setting, $default = null ) {
     426                $this->parse_post_data();
     427                if ( is_array( $this->_post_values ) && array_key_exists( $setting->id, $this->_post_values ) ) {
    418428                        return $setting->sanitize( $this->_post_values[ $setting->id ] );
     429                } else {
     430                        return $default;
     431                }
    419432        }
    420433
    421434        /**
  • 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 7a7be45..adfea11 100644
    class WP_Customize_Setting { 
    100100                        add_filter( "customize_sanitize_js_{$this->id}", $this->sanitize_js_callback, 10, 2 );
    101101        }
    102102
     103        protected $_original_value;
     104
    103105        /**
    104106         * Handle previewing the setting.
    105107         *
    106108         * @since 3.4.0
    107109         */
    108110        public function preview() {
     111
     112                if ( ! isset( $this->_original_value ) ) {
     113                        $this->_original_value = $this->value();
     114                }
     115
    109116                switch( $this->type ) {
    110117                        case 'theme_mod' :
    111118                                add_filter( 'theme_mod_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) );
    class WP_Customize_Setting { 
    156163         * @return mixed New or old value.
    157164         */
    158165        public function _preview_filter( $original ) {
    159                 return $this->multidimensional_replace( $original, $this->id_data[ 'keys' ], $this->post_value() );
     166                $undefined = new stdClass(); // symbol hack
     167                $post_value = $this->manager->post_value( $this, $undefined );
     168                if ( $undefined === $post_value ) {
     169                        $value = $this->_original_value;
     170                } else {
     171                        $value = $post_value;
     172                }
     173                $replaced = $this->multidimensional_replace( $original, $this->id_data['keys'], $value );
     174                return $replaced;
    160175        }
    161176
    162177        /**
    class WP_Customize_Setting { 
    422437                        $node = &$node[ $key ];
    423438                }
    424439
    425                 if ( $create && ! isset( $node[ $last ] ) )
    426                         $node[ $last ] = array();
     440                if ( $create ) {
     441                        if ( ! is_array( $node ) ) {
     442                                // account for an array overriding a string or object value
     443                                $node = array();
     444                        }
     445                        if ( ! isset( $node[ $last ] ) ) {
     446                                $node[ $last ] = array();
     447                        }
     448                }
    427449
    428450                if ( ! isset( $node[ $last ] ) )
    429451                        return;
  • new file tests/phpunit/tests/customize/setting.php

    diff --git tests/phpunit/tests/customize/setting.php tests/phpunit/tests/customize/setting.php
    new file mode 100644
    index 0000000..39aed05
    - +  
     1<?php
     2
     3/**
     4 * Tests specific to sites in multisite.
     5 *
     6 * @group customize
     7 */
     8class Tests_WP_Customize_Setting extends WP_UnitTestCase {
     9
     10        /**
     11         * @var WP_Customize_Manager
     12         */
     13        protected $manager;
     14
     15        function setUp() {
     16                parent::setUp();
     17                require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
     18                $GLOBALS['wp_customize'] = new WP_Customize_Manager(); // wpcs: override ok
     19                $this->manager = $GLOBALS['wp_customize'];
     20        }
     21
     22        function tearDown() {
     23                parent::tearDown();
     24                $this->manager = null;
     25                unset( $GLOBALS['wp_customize'] );
     26        }
     27
     28        function test_construct() {
     29                $foo = new WP_Customize_Setting( $this->manager, 'foo' );
     30                $this->assertEquals( $this->manager, $foo->manager );
     31                $this->assertEquals( 'foo', $foo->id );
     32                $this->assertEquals( 'theme_mod', $foo->type );
     33                $this->assertEquals( 'edit_theme_options', $foo->capability );
     34                $this->assertEquals( '', $foo->theme_supports );
     35                $this->assertEquals( '', $foo->default );
     36                $this->assertEquals( 'refresh', $foo->transport );
     37                $this->assertEquals( '', $foo->sanitize_callback );
     38                $this->assertEquals( '', $foo->sanitize_js_callback );
     39                $this->assertFalse( has_filter( "customize_sanitize_{$foo->id}" ) );
     40                $this->assertFalse( has_filter( "customize_sanitize_js_{$foo->id}" ) );
     41
     42                $args = array(
     43                        'type' => 'option',
     44                        'capability' => 'edit_posts',
     45                        'theme_supports' => 'widgets',
     46                        'default' => 'barbar',
     47                        'transport' => 'postMessage',
     48                        'sanitize_callback' => function ( $value ) { return $value . ':sanitize_callback'; },
     49                        'sanitize_js_callback' => function ( $value ) { return $value . ':sanitize_js_callback'; },
     50                );
     51                $bar = new WP_Customize_Setting( $this->manager, 'bar', $args );
     52                $this->assertEquals( 'bar', $bar->id );
     53                foreach ( $args as $key => $value ) {
     54                        $this->assertEquals( $value, $bar->$key );
     55                }
     56                $this->assertEquals( 10, has_filter( "customize_sanitize_{$bar->id}", $args['sanitize_callback'] ) );
     57                $this->assertEquals( 10, has_filter( "customize_sanitize_js_{$bar->id}" ), $args['sanitize_js_callback'] );
     58        }
     59
     60        function test_preview_standard_types() {
     61
     62                $post_data_overrides = array(
     63                        'unset_option_overridden' => 'unset_option_post_override_value',
     64                        'unset_theme_mod_overridden' => 'unset_theme_mod_post_override_value',
     65                        'set_option_overridden' => 'set_option_post_override_value',
     66                        'set_theme_mod_overridden' => 'set_theme_mod_post_override_value',
     67                        'unset_option_multi_overridden[foo]' => 'unset_option_multi_overridden[foo]_post_override_value',
     68                        'unset_theme_mod_multi_overridden[foo]' => 'unset_theme_mod_multi_overridden[foo]_post_override_value',
     69                        'set_option_multi_overridden[foo]' => 'set_option_multi_overridden[foo]_post_override_value',
     70                        'set_theme_mod_multi_overridden[foo]' => 'set_theme_mod_multi_overridden[foo]_post_override_value',
     71                );
     72
     73                // @todo this is hacky. The manager should provide a mechanism to override the post_values
     74                $_POST['customized'] = wp_slash( wp_json_encode( $post_data_overrides ) );
     75
     76                $undefined = new stdClass();
     77                $types = array(
     78                        'option' => array(
     79                                'getter' => 'get_option',
     80                                'setter' => 'update_option',
     81                        ),
     82                        'theme_mod' => array(
     83                                'getter' => 'get_theme_mod',
     84                                'setter' => 'set_theme_mod',
     85                        ),
     86                );
     87
     88                // Try non-multidimensional settings
     89                foreach ( $types as $type => $type_options ) {
     90                        // Non-multidimensional: See what effect the preview filter has on a non-existent setting (default value should be seen)
     91                        $name = "unset_{$type}_without_post_value";
     92                        $default = "default_value_{$name}";
     93                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     94                        $this->assertEquals( $undefined, call_user_func( $type_options['getter'], $name, $undefined ) );
     95                        $this->assertEquals( $default, $setting->value() );
     96                        $setting->preview();
     97                        $this->assertEquals( $default, call_user_func( $type_options['getter'], $name, $undefined ) );
     98                        $this->assertEquals( $default, $setting->value() );
     99
     100                        // Non-multidimensional: See what effect the preview has on an extant setting (default value should not be seen)
     101                        $name = "set_{$type}_without_post_value";
     102                        $default = "default_value_{$name}";
     103                        $initial_value = "initial_value_{$name}";
     104                        call_user_func( $type_options['setter'], $name, $initial_value );
     105                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     106                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name ) );
     107                        $this->assertEquals( $initial_value, $setting->value() );
     108                        $setting->preview();
     109                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
     110                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     111                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name ) );
     112                        $this->assertEquals( $initial_value, $setting->value() );
     113
     114                        // @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
     115                        $overridden_value = "overridden_value_$name";
     116                        call_user_func( $type_options['setter'], $name, $overridden_value );
     117                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name ) );
     118                        $this->assertEquals( $initial_value, $setting->value() );
     119                        $this->assertNotEquals( $overridden_value, $setting->value() );
     120
     121                        // Non-multidimensional: Test unset setting being overridden by a post value
     122                        $name = "unset_{$type}_overridden";
     123                        $default = "default_value_{$name}";
     124                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     125                        $this->assertEquals( $undefined, call_user_func( $type_options['getter'], $name, $undefined ) );
     126                        $this->assertEquals( $default, $setting->value() );
     127                        $setting->preview(); // activate post_data
     128                        $this->assertEquals( $post_data_overrides[ $name ], call_user_func( $type_options['getter'], $name, $undefined ) );
     129                        $this->assertEquals( $post_data_overrides[ $name ], $setting->value() );
     130
     131                        // Non-multidimensional: Test set setting being overridden by a post value
     132                        $name = "set_{$type}_overridden";
     133                        $default = "default_value_{$name}";
     134                        $initial_value = "initial_value_{$name}";
     135                        call_user_func( $type_options['setter'], $name, $initial_value );
     136                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     137                        $this->assertEquals( $initial_value, call_user_func( $type_options['getter'], $name, $undefined ) );
     138                        $this->assertEquals( $initial_value, $setting->value() );
     139                        $setting->preview(); // activate post_data
     140                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
     141                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     142                        $this->assertEquals( $post_data_overrides[ $name ], call_user_func( $type_options['getter'], $name, $undefined ) );
     143                        $this->assertEquals( $post_data_overrides[ $name ], $setting->value() );
     144                }
     145
     146                // Try multidimensional settings
     147                foreach ( $types as $type => $type_options ) {
     148                        // Multidimensional: See what effect the preview filter has on a non-existent setting (default value should be seen)
     149                        $base_name = "unset_{$type}_multi";
     150                        $name = $base_name . '[foo]';
     151                        $default = "default_value_{$name}";
     152                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     153                        $this->assertEquals( $undefined, call_user_func( $type_options['getter'], $base_name, $undefined ) );
     154                        $this->assertEquals( $default, $setting->value() );
     155                        $setting->preview();
     156                        $base_value = call_user_func( $type_options['getter'], $base_name, $undefined );
     157                        $this->assertArrayHasKey( 'foo', $base_value );
     158                        $this->assertEquals( $default, $base_value['foo'] );
     159
     160                        // Multidimensional: See what effect the preview has on an extant setting (default value should not be seen)
     161                        $base_name = "set_{$type}_multi";
     162                        $name = $base_name . '[foo]';
     163                        $default = "default_value_{$name}";
     164                        $initial_value = "initial_value_{$name}";
     165                        $base_initial_value = array( 'foo' => $initial_value, 'bar' => 'persisted' );
     166                        call_user_func( $type_options['setter'], $base_name, $base_initial_value );
     167                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     168                        $base_value = call_user_func( $type_options['getter'], $base_name, array() );
     169                        $this->assertEquals( $initial_value, $base_value['foo'] );
     170                        $this->assertEquals( $initial_value, $setting->value() );
     171                        $setting->preview();
     172                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
     173                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     174                        $base_value = call_user_func( $type_options['getter'], $base_name, array() );
     175                        $this->assertEquals( $initial_value, $base_value['foo'] );
     176                        $this->assertEquals( $initial_value, $setting->value() );
     177
     178                        // Multidimensional: Test unset setting being overridden by a post value
     179                        $base_name = "unset_{$type}_multi_overridden";
     180                        $name = $base_name . '[foo]';
     181                        $default = "default_value_{$name}";
     182                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     183                        $this->assertEquals( $undefined, call_user_func( $type_options['getter'], $base_name, $undefined ) );
     184                        $this->assertEquals( $default, $setting->value() );
     185                        $setting->preview();
     186                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
     187                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     188                        $base_value = call_user_func( $type_options['getter'], $base_name, $undefined );
     189                        $this->assertArrayHasKey( 'foo', $base_value );
     190                        $this->assertEquals( $post_data_overrides[ $name ], $base_value['foo'] );
     191
     192                        // Multidimemsional: Test set setting being overridden by a post value
     193                        $base_name = "set_{$type}_multi_overridden";
     194                        $name = $base_name . '[foo]';
     195                        $default = "default_value_{$name}";
     196                        $initial_value = "initial_value_{$name}";
     197                        $base_initial_value = array( 'foo' => $initial_value, 'bar' => 'persisted' );
     198                        call_user_func( $type_options['setter'], $base_name, $base_initial_value );
     199                        $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     200                        $base_value = call_user_func( $type_options['getter'], $base_name, $undefined );
     201                        $this->arrayHasKey( 'foo', $base_value );
     202                        $this->arrayHasKey( 'bar', $base_value );
     203                        $this->assertEquals( $base_initial_value['foo'], $base_value['foo'] );
     204                        $this->assertEquals( $base_initial_value['bar'], call_user_func( $type_options['getter'], $base_name, $undefined )['bar'] );
     205                        $this->assertEquals( $initial_value, $setting->value() );
     206                        $setting->preview();
     207                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->id}" ) ); // only applicable for custom types (not options or theme_mods)
     208                        $this->assertEquals( 0, did_action( "customize_preview_{$setting->type}" ) ); // only applicable for custom types (not options or theme_mods)
     209                        $base_value = call_user_func( $type_options['getter'], $base_name, $undefined );
     210                        $this->assertArrayHasKey( 'foo', $base_value );
     211                        $this->assertEquals( $post_data_overrides[ $name ], $base_value['foo'] );
     212                        $this->arrayHasKey( 'bar', call_user_func( $type_options['getter'], $base_name, $undefined ) );
     213                        $this->assertEquals( $base_initial_value['bar'], call_user_func( $type_options['getter'], $base_name, $undefined )['bar'] );
     214                }
     215        }
     216
     217        function test_preview_custom_type() {
     218                $type = 'custom_type';
     219                $post_data_overrides = array(
     220                        "unset_{$type}_with_post_value" => "unset_{$type}_without_post_value",
     221                        "set_{$type}_with_post_value" => "set_{$type}_without_post_value",
     222                );
     223                $_POST['customized'] = wp_slash( wp_json_encode( $post_data_overrides ) );
     224
     225                $custom_type_data_saved = array();
     226                $custom_type_data_previewed = array();
     227                $undefined = new stdClass();
     228
     229                $getter = function ( $name, $default = null ) use ( &$custom_type_data_saved, &$custom_type_data_previewed ) {
     230                        if ( did_action( "customize_preview_{$name}" ) && array_key_exists( $name, $custom_type_data_previewed ) ) {
     231                                $value = $custom_type_data_previewed[ $name ];
     232                        } else if ( array_key_exists( $name, $custom_type_data_saved ) ) {
     233                                $value = $custom_type_data_saved[ $name ];
     234                        } else {
     235                                $value = $default;
     236                        }
     237                        return $value;
     238                };
     239
     240                $setter = function ( $name, $value ) use ( &$custom_type_data_saved ) {
     241                        $custom_type_data_saved[ $name ] = $value;
     242                };
     243
     244                add_action( "customize_preview_{$type}", function ( $setting ) use ( &$custom_type_data_previewed, $undefined ) {
     245                        /**
     246                         * @var WP_Customize_Setting $setting
     247                         */
     248                        $previewed_value = $setting->post_value( $undefined );
     249                        if ( $undefined !== $previewed_value ) {
     250                                $custom_type_data_previewed[ $setting->id ] = $previewed_value;
     251                        }
     252                } );
     253
     254                // Custom type not existing and no post value override
     255                $name = "unset_{$type}_without_post_value";
     256                $default = "default_value_{$name}";
     257                $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     258                // Note: #29316 will allow us to have one filter for all settings of a given type, which is what we need
     259                add_filter( "customize_value_{$name}", function ( $default ) use ( $getter, $name ) {
     260                        return call_user_func( $getter, $name, $default );
     261                } );
     262                $this->assertEquals( $undefined, call_user_func( $getter, $name, $undefined ) );
     263                $this->assertEquals( $default, $setting->value() );
     264                $setting->preview();
     265                $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
     266                $this->assertEquals( 1, did_action( "customize_preview_{$setting->type}" ) );
     267                $this->assertEquals( $undefined, call_user_func( $getter, $name, $undefined ) ); // Note: for a non-custom type this is $default
     268                $this->assertEquals( $default, $setting->value() ); // should be same as above
     269
     270                // Custom type existing and no post value override
     271                $name = "set_{$type}_without_post_value";
     272                $default = "default_value_{$name}";
     273                $initial_value = "initial_value_{$name}";
     274                call_user_func( $setter, $name, $initial_value );
     275                $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     276                // Note: #29316 will allow us to have one filter for all settings of a given type, which is what we need
     277                add_filter( "customize_value_{$name}", function ( $default ) use ( $getter, $name ) {
     278                        return call_user_func( $getter, $name, $default );
     279                } );
     280                $this->assertEquals( $initial_value, call_user_func( $getter, $name, $undefined ) );
     281                $this->assertEquals( $initial_value, $setting->value() );
     282                $setting->preview();
     283                $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
     284                $this->assertEquals( 2, did_action( "customize_preview_{$setting->type}" ) );
     285                $this->assertEquals( $initial_value, call_user_func( $getter, $name, $undefined ) ); // should be same as above
     286                $this->assertEquals( $initial_value, $setting->value() ); // should be same as above
     287
     288                // Custom type not existing and with a post value override
     289                $name = "unset_{$type}_with_post_value";
     290                $default = "default_value_{$name}";
     291                $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     292                // Note: #29316 will allow us to have one filter for all settings of a given type, which is what we need
     293                add_filter( "customize_value_{$name}", function ( $default ) use ( $getter, $name ) {
     294                        return call_user_func( $getter, $name, $default );
     295                } );
     296                $this->assertEquals( $undefined, call_user_func( $getter, $name, $undefined ) );
     297                $this->assertEquals( $default, $setting->value() );
     298                $setting->preview();
     299                $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
     300                $this->assertEquals( 3, did_action( "customize_preview_{$setting->type}" ) );
     301                $this->assertEquals( $post_data_overrides[ $name ], call_user_func( $getter, $name, $undefined ) );
     302                $this->assertEquals( $post_data_overrides[ $name ], $setting->value() );
     303
     304                // Custom type not existing and with a post value override
     305                $name = "set_{$type}_with_post_value";
     306                $default = "default_value_{$name}";
     307                $initial_value = "initial_value_{$name}";
     308                call_user_func( $setter, $name, $initial_value );
     309                $setting = new WP_Customize_Setting( $this->manager, $name, compact( 'type', 'default' ) );
     310                // Note: #29316 will allow us to have one filter for all settings of a given type, which is what we need
     311                add_filter( "customize_value_{$name}", function ( $default ) use ( $getter, $name ) {
     312                        return call_user_func( $getter, $name, $default );
     313                } );
     314                $this->assertEquals( $initial_value, call_user_func( $getter, $name, $undefined ) );
     315                $this->assertEquals( $initial_value, $setting->value() );
     316                $setting->preview();
     317                $this->assertEquals( 1, did_action( "customize_preview_{$setting->id}" ) );
     318                $this->assertEquals( 4, did_action( "customize_preview_{$setting->type}" ) );
     319                $this->assertEquals( $post_data_overrides[ $name ], call_user_func( $getter, $name, $undefined ) );
     320                $this->assertEquals( $post_data_overrides[ $name ], $setting->value() );
     321
     322        }
     323
     324        // @todo function test_save() {
     325        // @todo test do_action( 'customize_save_' . $this->id_data[ 'base' ], $this );
     326        // @todo test_post_value()
     327        // @todo test_sanitize( $value )
     328        // @todo apply_filters( "customize_sanitize_{$this->id}", $value, $this );
     329        // @todo function update( $value )
     330        // @todo test_value()
     331        // @todo test customize_value_{$name} filter
     332        // @todo test_js_value()
     333        // @todo test apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this );
     334        // @todo test_check_capabilities() {
     335
     336        // @todo final protected function multidimensional( &$root, $keys, $create = false )
     337        // @todo final protected function multidimensional_replace( $root, $keys, $value )
     338        // @todo final protected function multidimensional_get( $root, $keys, $default = null ) {
     339        // @todo final protected function multidimensional_isset( $root, $keys )
     340}
     341