WordPress.org

Make WordPress Core

Changeset 39320


Ignore:
Timestamp:
11/19/2016 10:38:40 PM (19 months ago)
Author:
westonruter
Message:

Customize: Ensure that WP_Customize_Manager::save_changeset_post() returns setting_validities even for supplied values that are unchanged from values in changeset.

Check setting existence and authorization via WP_Customize_Manager::validate_setting_values() even for null values to account for custom params being added to settings, preventing failures from being silently ignored.

See #38705, #30937.
Fixes #38865.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r39276 r39320  
    17291729                continue;
    17301730            }
    1731             if ( is_null( $unsanitized_value ) ) {
    1732                 continue;
    1733             }
    17341731            if ( $options['validate_capability'] && ! current_user_can( $setting->capability ) ) {
    17351732                $validity = new WP_Error( 'unauthorized', __( 'Unauthorized to modify setting due to capability.' ) );
    17361733            } else {
     1734                if ( is_null( $unsanitized_value ) ) {
     1735                    continue;
     1736                }
    17371737                $validity = $setting->validate( $unsanitized_value );
    17381738            }
     
    20312031            }
    20322032        }
    2033         $post_values = wp_array_slice_assoc( $post_values, $changed_setting_ids );
    20342033
    20352034        /**
     
    20472046
    20482047        // Validate settings.
    2049         $setting_validities = $this->validate_setting_values( $post_values, array(
     2048        $validated_values = array_merge(
     2049            array_fill_keys( array_keys( $args['data'] ), null ), // Make sure existence/capability checks are done on value-less setting updates.
     2050            $post_values
     2051        );
     2052        $setting_validities = $this->validate_setting_values( $validated_values, array(
    20502053            'validate_capability' => true,
    20512054            'validate_existence' => true,
     
    20652068        }
    20662069
    2067         $response = array(
    2068             'setting_validities' => $setting_validities,
    2069         );
    2070 
    20712070        // Obtain/merge data for changeset.
    20722071        $original_changeset_data = $this->get_changeset_post_data( $changeset_post_id );
     
    21062105                unset( $data[ $changeset_setting_id ] );
    21072106            } else {
    2108                 // Merge any additional setting params that have been supplied with the existing params.
     2107
    21092108                if ( ! isset( $data[ $changeset_setting_id ] ) ) {
    21102109                    $data[ $changeset_setting_id ] = array();
    21112110                }
    21122111
     2112                // Merge any additional setting params that have been supplied with the existing params.
     2113                $merged_setting_params = array_merge( $data[ $changeset_setting_id ], $setting_params );
     2114
     2115                // Skip updating setting params if unchanged (ensuring the user_id is not overwritten).
     2116                if ( $data[ $changeset_setting_id ] === $merged_setting_params ) {
     2117                    continue;
     2118                }
     2119
    21132120                $data[ $changeset_setting_id ] = array_merge(
    2114                     $data[ $changeset_setting_id ],
    2115                     $setting_params,
     2121                    $merged_setting_params,
    21162122                    array(
    21172123                        'type' => $setting->type,
     
    22202226
    22212227        remove_filter( 'wp_save_post_revision_post_has_changed', array( $this, '_filter_revision_post_has_changed' ) );
     2228
     2229        $response = array(
     2230            'setting_validities' => $setting_validities,
     2231        );
    22222232
    22232233        if ( is_wp_error( $r ) ) {
  • trunk/tests/phpunit/tests/customize/manager.php

    r39276 r39320  
    861861
    862862        $uuid = wp_generate_uuid4();
    863         $manager = new WP_Customize_Manager( array(
    864             'changeset_uuid' => $uuid,
    865         ) );
    866         $wp_customize = $manager;
    867         do_action( 'customize_register', $manager );
    868         $manager->add_setting( 'scratchpad', array(
    869             'type' => 'option',
    870             'capability' => 'exist',
    871         ) );
    872 
    873         // Create initial set of
    874         $r = $manager->save_changeset_post( array(
     863        $wp_customize = $this->create_test_manager( $uuid );
     864        $r = $wp_customize->save_changeset_post( array(
    875865            'status' => 'auto-draft',
    876866            'data' => array(
     
    891881            $r['setting_validities']
    892882        );
    893         $post_id = $manager->find_changeset_post_id( $uuid );
     883        $post_id = $wp_customize->find_changeset_post_id( $uuid );
    894884        $data = json_decode( get_post( $post_id )->post_content, true );
    895885        $this->assertEquals( self::$admin_user_id, $data['blogname']['user_id'] );
     
    899889        // Attempt to save just one setting under a different user.
    900890        wp_set_current_user( $other_admin_user_id );
    901         $r = $manager->save_changeset_post( array(
     891        $wp_customize = $this->create_test_manager( $uuid );
     892        $r = $wp_customize->save_changeset_post( array(
    902893            'status' => 'auto-draft',
    903894            'data' => array(
     
    924915
    925916        // Attempt to save now as under-privileged user.
    926         $r = $manager->save_changeset_post( array(
     917        $wp_customize = $this->create_test_manager( $uuid );
     918        $r = $wp_customize->save_changeset_post( array(
    927919            'status' => 'auto-draft',
    928920            'data' => array(
     921                'blogname' => array(
     922                    'value' => 'Admin 2 Title', // Identical to what is already in the changeset so will be skipped.
     923                ),
    929924                'scratchpad' => array(
    930925                    'value' => 'Subscriber Scratch',
     
    935930        $this->assertInternalType( 'array', $r );
    936931        $this->assertEquals(
    937             array_fill_keys( array( 'scratchpad' ), true ),
     932            array_fill_keys( array( 'scratchpad', 'blogname' ), true ),
    938933            $r['setting_validities']
    939934        );
    940935        $data = json_decode( get_post( $post_id )->post_content, true );
    941         $this->assertEquals( $other_admin_user_id, $data['blogname']['user_id'] );
     936        $this->assertEquals( $other_admin_user_id, $data['blogname']['user_id'], 'Expected setting to be untouched.' );
    942937        $this->assertEquals( self::$subscriber_user_id, $data['scratchpad']['user_id'] );
    943938        $this->assertEquals( $other_admin_user_id, $data[ $this->manager->get_stylesheet() . '::background_color' ]['user_id'] );
     
    956951        }
    957952        $this->filtered_setting_current_user_ids = array();
    958         foreach ( $manager->settings() as $setting ) {
     953        foreach ( $wp_customize->settings() as $setting ) {
    959954            add_filter( sprintf( 'customize_sanitize_%s', $setting->id ), array( $this, 'filter_customize_setting_to_log_current_user' ), 10, 2 );
    960955        }
     
    970965        $this->assertEquals( $other_admin_user_id, $this->filtered_setting_current_user_ids['background_color'] );
    971966        $this->assertEquals( 'Subscriber Scratch', get_option( 'scratchpad' ) );
     967    }
     968
     969    /**
     970     * Create test manager.
     971     *
     972     * @param string $uuid Changeset UUID.
     973     * @return WP_Customize_Manager Manager.
     974     */
     975    protected function create_test_manager( $uuid ) {
     976        $manager = new WP_Customize_Manager( array(
     977            'changeset_uuid' => $uuid,
     978        ) );
     979        do_action( 'customize_register', $manager );
     980        $manager->add_setting( 'blogfounded', array(
     981            'type' => 'option',
     982        ) );
     983        $manager->add_setting( 'blogterminated', array(
     984            'type' => 'option',
     985            'capability' => 'do_not_allow',
     986        ) );
     987        $manager->add_setting( 'scratchpad', array(
     988            'type' => 'option',
     989            'capability' => 'exist',
     990        ) );
     991        return $manager;
     992    }
     993
     994    /**
     995     * Test writing changesets when user supplies unchanged values.
     996     *
     997     * @ticket 38865
     998     * @covers WP_Customize_Manager::save_changeset_post()
     999     */
     1000    function test_save_changeset_post_with_unchanged_values() {
     1001        global $wp_customize;
     1002
     1003        add_theme_support( 'custom-background' );
     1004        wp_set_current_user( self::$admin_user_id );
     1005        $other_admin_user_id = self::factory()->user->create( array( 'role' => 'administrator' ) );
     1006
     1007        $uuid = wp_generate_uuid4();
     1008        $wp_customize = $this->create_test_manager( $uuid );
     1009        $wp_customize->save_changeset_post( array(
     1010            'status' => 'auto-draft',
     1011            'data' => array(
     1012                'blogname' => array(
     1013                    'value' => 'Admin 1 Title',
     1014                ),
     1015                'blogdescription' => array(
     1016                    'value' => 'Admin 1 Tagline',
     1017                ),
     1018                'blogfounded' => array(
     1019                    'value' => '2016',
     1020                ),
     1021                'scratchpad' => array(
     1022                    'value' => 'Admin 1 Scratch',
     1023                ),
     1024            ),
     1025        ) );
     1026
     1027        // Make sure that setting properties of unknown and unauthorized settings are rejected.
     1028        $data = get_post( $wp_customize->changeset_post_id() )->post_content;
     1029        $r = $wp_customize->save_changeset_post( array(
     1030            'data' => array(
     1031                'unknownsetting' => array(
     1032                    'custom' => 'prop',
     1033                ),
     1034                'blogterminated' => array(
     1035                    'custom' => 'prop',
     1036                ),
     1037            ),
     1038        ) );
     1039        $this->assertInstanceOf( 'WP_Error', $r['setting_validities']['unknownsetting'] );
     1040        $this->assertEquals( 'unrecognized', $r['setting_validities']['unknownsetting']->get_error_code() );
     1041        $this->assertInstanceOf( 'WP_Error', $r['setting_validities']['blogterminated'] );
     1042        $this->assertEquals( 'unauthorized', $r['setting_validities']['blogterminated']->get_error_code() );
     1043        $this->assertEquals( $data, get_post( $wp_customize->changeset_post_id() )->post_content );
     1044
     1045        // Test submitting data with changed and unchanged settings, creating a new instance so that the post_values are cleared.
     1046        wp_set_current_user( $other_admin_user_id );
     1047        $wp_customize = $this->create_test_manager( $uuid );
     1048        $r = $wp_customize->save_changeset_post( array(
     1049            'status' => 'auto-draft',
     1050            'data' => array(
     1051                'blogname' => array(
     1052                    'value' => 'Admin 1 Title', // Unchanged value.
     1053                ),
     1054                'blogdescription' => array(
     1055                    'value' => 'Admin 1 Tagline Changed', // Changed value.
     1056                ),
     1057                'blogfounded' => array(
     1058                    'extra' => 'blogfounded_param', // New param.
     1059                ),
     1060                'scratchpad' => array(
     1061                    'value' => 'Admin 1 Scratch', // Unchanged value.
     1062                    'extra' => 'background_scratchpad2', // New param.
     1063                ),
     1064            ),
     1065        ) );
     1066
     1067        // Note that blogfounded is not included among setting_validities because no value was supplied and it is not unrecognized/unauthorized.
     1068        $this->assertEquals( array_fill_keys( array( 'blogname', 'blogdescription', 'scratchpad' ), true ), $r['setting_validities'], 'Expected blogname even though unchanged.' );
     1069
     1070        $data = json_decode( get_post( $wp_customize->changeset_post_id() )->post_content, true );
     1071
     1072        $this->assertEquals( self::$admin_user_id, $data['blogname']['user_id'], 'Expected unchanged user_id since value was unchanged.' );
     1073        $this->assertEquals( $other_admin_user_id, $data['blogdescription']['user_id'] );
     1074        $this->assertEquals( $other_admin_user_id, $data['blogfounded']['user_id'] );
     1075        $this->assertEquals( $other_admin_user_id, $data['scratchpad']['user_id'] );
    9721076    }
    9731077
Note: See TracChangeset for help on using the changeset viewer.