Make WordPress Core


Ignore:
Timestamp:
10/18/2016 08:04:36 PM (10 years ago)
Author:
westonruter
Message:

Customize: Implement customized state persistence with changesets.

Includes infrastructure developed in the Customize Snapshots feature plugin.

See https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/

Props westonruter, valendesigns, utkarshpatel, stubgo, lgedeon, ocean90, ryankienstra, mihai2u, dlh, aaroncampbell, jonathanbardo, jorbin.
See #28721.
See #31089.
Fixes #30937.
Fixes #31517.
Fixes #30028.
Fixes #23225.
Fixes #34142.
Fixes #36485.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/customize/manager.php

    r38765 r38810  
    2828
    2929        /**
     30         * Admin user ID.
     31         *
     32         * @var int
     33         */
     34        protected static $admin_user_id;
     35
     36        /**
     37         * Subscriber user ID.
     38         *
     39         * @var int
     40         */
     41        protected static $subscriber_user_id;
     42
     43        /**
     44         * Set up before class.
     45         *
     46         * @param WP_UnitTest_Factory $factory Factory.
     47         */
     48        public static function wpSetUpBeforeClass( $factory ) {
     49                self::$subscriber_user_id = $factory->user->create( array( 'role' => 'subscriber' ) );
     50                self::$admin_user_id = $factory->user->create( array( 'role' => 'administrator' ) );
     51        }
     52
     53        /**
    3054         * Set up test.
    3155         */
     
    4367                $this->manager = null;
    4468                unset( $GLOBALS['wp_customize'] );
     69                $_REQUEST = array();
    4570                parent::tearDown();
    4671        }
     
    5479                $GLOBALS['wp_customize'] = new WP_Customize_Manager();
    5580                return $GLOBALS['wp_customize'];
     81        }
     82
     83        /**
     84         * Test WP_Customize_Manager::__construct().
     85         *
     86         * @covers WP_Customize_Manager::__construct()
     87         */
     88        function test_constructor() {
     89                $uuid = wp_generate_uuid4();
     90                $theme = 'twentyfifteen';
     91                $messenger_channel = 'preview-123';
     92                $wp_customize = new WP_Customize_Manager( array(
     93                        'changeset_uuid' => $uuid,
     94                        'theme' => $theme,
     95                        'messenger_channel' => $messenger_channel,
     96                ) );
     97                $this->assertEquals( $uuid, $wp_customize->changeset_uuid() );
     98                $this->assertEquals( $theme, $wp_customize->get_stylesheet() );
     99                $this->assertEquals( $messenger_channel, $wp_customize->get_messenger_channel() );
     100
     101                $theme = 'twentyfourteen';
     102                $messenger_channel = 'preview-456';
     103                $_REQUEST['theme'] = $theme;
     104                $_REQUEST['customize_messenger_channel'] = $messenger_channel;
     105                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     106                $this->assertEquals( $theme, $wp_customize->get_stylesheet() );
     107                $this->assertEquals( $messenger_channel, $wp_customize->get_messenger_channel() );
     108
     109                $theme = 'twentyfourteen';
     110                $_REQUEST['customize_theme'] = $theme;
     111                $wp_customize = new WP_Customize_Manager();
     112                $this->assertEquals( $theme, $wp_customize->get_stylesheet() );
     113                $this->assertNotEmpty( $wp_customize->changeset_uuid() );
     114        }
     115
     116        /**
     117         * Test WP_Customize_Manager::setup_theme() for admin screen.
     118         *
     119         * @covers WP_Customize_Manager::setup_theme()
     120         */
     121        function test_setup_theme_in_customize_admin() {
     122                global $pagenow, $wp_customize;
     123                $pagenow = 'customize.php';
     124                set_current_screen( 'customize' );
     125
     126                // Unauthorized.
     127                $exception = null;
     128                $wp_customize = new WP_Customize_Manager();
     129                wp_set_current_user( self::$subscriber_user_id );
     130                try {
     131                        $wp_customize->setup_theme();
     132                } catch ( Exception $e ) {
     133                        $exception = $e;
     134                }
     135                $this->assertInstanceOf( 'WPDieException', $exception );
     136                $this->assertContains( 'you are not allowed to customize this site', $exception->getMessage() );
     137
     138                // Bad changeset.
     139                $exception = null;
     140                wp_set_current_user( self::$admin_user_id );
     141                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => 'bad' ) );
     142                try {
     143                        $wp_customize->setup_theme();
     144                } catch ( Exception $e ) {
     145                        $exception = $e;
     146                }
     147                $this->assertInstanceOf( 'WPDieException', $exception );
     148                $this->assertContains( 'Invalid changeset UUID', $exception->getMessage() );
     149
     150                $wp_customize = new WP_Customize_Manager();
     151                $wp_customize->setup_theme();
     152        }
     153
     154        /**
     155         * Test WP_Customize_Manager::setup_theme() for frontend.
     156         *
     157         * @covers WP_Customize_Manager::setup_theme()
     158         */
     159        function test_setup_theme_in_frontend() {
     160                global $wp_customize, $pagenow, $show_admin_bar;
     161                $pagenow = 'front';
     162                set_current_screen( 'front' );
     163
     164                wp_set_current_user( 0 );
     165                $exception = null;
     166                $wp_customize = new WP_Customize_Manager();
     167                wp_set_current_user( self::$subscriber_user_id );
     168                try {
     169                        $wp_customize->setup_theme();
     170                } catch ( Exception $e ) {
     171                        $exception = $e;
     172                }
     173                $this->assertInstanceOf( 'WPDieException', $exception );
     174                $this->assertContains( 'Non-existent changeset UUID', $exception->getMessage() );
     175
     176                wp_set_current_user( self::$admin_user_id );
     177                $wp_customize = new WP_Customize_Manager( array( 'messenger_channel' => 'preview-1' ) );
     178                $wp_customize->setup_theme();
     179                $this->assertFalse( $show_admin_bar );
     180
     181                show_admin_bar( true );
     182                wp_set_current_user( self::$admin_user_id );
     183                $wp_customize = new WP_Customize_Manager( array( 'messenger_channel' => null ) );
     184                $wp_customize->setup_theme();
     185                $this->assertTrue( $show_admin_bar );
     186        }
     187
     188        /**
     189         * Test WP_Customize_Manager::changeset_uuid().
     190         *
     191         * @ticket 30937
     192         * @covers WP_Customize_Manager::changeset_uuid()
     193         */
     194        function test_changeset_uuid() {
     195                $uuid = wp_generate_uuid4();
     196                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     197                $this->assertEquals( $uuid, $wp_customize->changeset_uuid() );
     198        }
     199
     200        /**
     201         * Test WP_Customize_Manager::wp_loaded().
     202         *
     203         * Ensure that post values are previewed even without being in preview.
     204         *
     205         * @ticket 30937
     206         * @covers WP_Customize_Manager::wp_loaded()
     207         */
     208        function test_wp_loaded() {
     209                wp_set_current_user( self::$admin_user_id );
     210                $wp_customize = new WP_Customize_Manager();
     211                $title = 'Hello World';
     212                $wp_customize->set_post_value( 'blogname', $title );
     213                $this->assertNotEquals( $title, get_option( 'blogname' ) );
     214                $wp_customize->wp_loaded();
     215                $this->assertFalse( $wp_customize->is_preview() );
     216                $this->assertEquals( $title, $wp_customize->get_setting( 'blogname' )->value() );
     217                $this->assertEquals( $title, get_option( 'blogname' ) );
     218        }
     219
     220        /**
     221         * Test WP_Customize_Manager::find_changeset_post_id().
     222         *
     223         * @ticket 30937
     224         * @covers WP_Customize_Manager::find_changeset_post_id()
     225         */
     226        function test_find_changeset_post_id() {
     227                $uuid = wp_generate_uuid4();
     228                $post_id = $this->factory()->post->create( array(
     229                        'post_name' => $uuid,
     230                        'post_type' => 'customize_changeset',
     231                        'post_status' => 'auto-draft',
     232                        'post_content' => '{}',
     233                ) );
     234
     235                $wp_customize = new WP_Customize_Manager();
     236                $this->assertNull( $wp_customize->find_changeset_post_id( wp_generate_uuid4() ) );
     237                $this->assertEquals( $post_id, $wp_customize->find_changeset_post_id( $uuid ) );
     238        }
     239
     240        /**
     241         * Test WP_Customize_Manager::changeset_post_id().
     242         *
     243         * @ticket 30937
     244         * @covers WP_Customize_Manager::changeset_post_id()
     245         */
     246        function test_changeset_post_id() {
     247                $uuid = wp_generate_uuid4();
     248                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     249                $this->assertNull( $wp_customize->changeset_post_id() );
     250
     251                $uuid = wp_generate_uuid4();
     252                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     253                $post_id = $this->factory()->post->create( array(
     254                        'post_name' => $uuid,
     255                        'post_type' => 'customize_changeset',
     256                        'post_status' => 'auto-draft',
     257                        'post_content' => '{}',
     258                ) );
     259                $this->assertEquals( $post_id, $wp_customize->changeset_post_id() );
     260        }
     261
     262        /**
     263         * Test WP_Customize_Manager::changeset_data().
     264         *
     265         * @ticket 30937
     266         * @covers WP_Customize_Manager::changeset_data()
     267         */
     268        function test_changeset_data() {
     269                $uuid = wp_generate_uuid4();
     270                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     271                $this->assertEquals( array(), $wp_customize->changeset_data() );
     272
     273                $uuid = wp_generate_uuid4();
     274                $data = array( 'blogname' => array( 'value' => 'Hello World' ) );
     275                $this->factory()->post->create( array(
     276                        'post_name' => $uuid,
     277                        'post_type' => 'customize_changeset',
     278                        'post_status' => 'auto-draft',
     279                        'post_content' => wp_json_encode( $data ),
     280                ) );
     281                $wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     282                $this->assertEquals( $data, $wp_customize->changeset_data() );
     283        }
     284
     285        /**
     286         * Test WP_Customize_Manager::customize_preview_init().
     287         *
     288         * @ticket 30937
     289         * @covers WP_Customize_Manager::customize_preview_init()
     290         */
     291        function test_customize_preview_init() {
     292
     293                // Test authorized admin user.
     294                wp_set_current_user( self::$admin_user_id );
     295                $did_action_customize_preview_init = did_action( 'customize_preview_init' );
     296                $wp_customize = new WP_Customize_Manager();
     297                $wp_customize->customize_preview_init();
     298                $this->assertEquals( $did_action_customize_preview_init + 1, did_action( 'customize_preview_init' ) );
     299
     300                $this->assertEquals( 10, has_action( 'wp_head', 'wp_no_robots' ) );
     301                $this->assertEquals( 10, has_filter( 'wp_headers', array( $wp_customize, 'filter_iframe_security_headers' ) ) );
     302                $this->assertEquals( 10, has_filter( 'wp_redirect', array( $wp_customize, 'add_state_query_params' ) ) );
     303                $this->assertTrue( wp_script_is( 'customize-preview', 'enqueued' ) );
     304                $this->assertEquals( 10, has_action( 'wp_head', array( $wp_customize, 'customize_preview_loading_style' ) ) );
     305                $this->assertEquals( 20, has_action( 'wp_footer', array( $wp_customize, 'customize_preview_settings' ) ) );
     306
     307                // Test unauthorized user outside preview (no messenger_channel).
     308                wp_set_current_user( self::$subscriber_user_id );
     309                $wp_customize = new WP_Customize_Manager();
     310                $wp_customize->register_controls();
     311                $this->assertNotEmpty( $wp_customize->controls() );
     312                $wp_customize->customize_preview_init();
     313                $this->assertEmpty( $wp_customize->controls() );
     314
     315                // Test unauthorized user inside preview (with messenger_channel).
     316                wp_set_current_user( self::$subscriber_user_id );
     317                $wp_customize = new WP_Customize_Manager( array( 'messenger_channel' => 'preview-0' ) );
     318                $exception = null;
     319                try {
     320                        $wp_customize->customize_preview_init();
     321                } catch ( WPDieException $e ) {
     322                        $exception = $e;
     323                }
     324                $this->assertNotNull( $exception );
     325                $this->assertContains( 'Unauthorized', $exception->getMessage() );
     326        }
     327
     328        /**
     329         * Test WP_Customize_Manager::filter_iframe_security_headers().
     330         *
     331         * @ticket 30937
     332         * @covers WP_Customize_Manager::filter_iframe_security_headers()
     333         */
     334        function test_filter_iframe_security_headers() {
     335                $customize_url = admin_url( 'customize.php' );
     336                $wp_customize = new WP_Customize_Manager();
     337                $headers = $wp_customize->filter_iframe_security_headers( array() );
     338                $this->assertArrayHasKey( 'X-Frame-Options', $headers );
     339                $this->assertArrayHasKey( 'Content-Security-Policy', $headers );
     340                $this->assertEquals( "ALLOW-FROM $customize_url", $headers['X-Frame-Options'] );
     341        }
     342
     343        /**
     344         * Test WP_Customize_Manager::add_state_query_params().
     345         *
     346         * @ticket 30937
     347         * @covers WP_Customize_Manager::add_state_query_params()
     348         */
     349        function test_add_state_query_params() {
     350                $uuid = wp_generate_uuid4();
     351                $messenger_channel = 'preview-0';
     352                $wp_customize = new WP_Customize_Manager( array(
     353                        'changeset_uuid' => $uuid,
     354                        'messenger_channel' => $messenger_channel,
     355                ) );
     356                $url = $wp_customize->add_state_query_params( home_url( '/' ) );
     357                $parsed_url = wp_parse_url( $url );
     358                parse_str( $parsed_url['query'], $query_params );
     359                $this->assertArrayHasKey( 'customize_messenger_channel', $query_params );
     360                $this->assertArrayHasKey( 'customize_changeset_uuid', $query_params );
     361                $this->assertArrayNotHasKey( 'customize_theme', $query_params );
     362                $this->assertEquals( $uuid, $query_params['customize_changeset_uuid'] );
     363                $this->assertEquals( $messenger_channel, $query_params['customize_messenger_channel'] );
     364
     365                $uuid = wp_generate_uuid4();
     366                $wp_customize = new WP_Customize_Manager( array(
     367                        'changeset_uuid' => $uuid,
     368                        'messenger_channel' => null,
     369                        'theme' => 'twentyfifteen',
     370                ) );
     371                $url = $wp_customize->add_state_query_params( home_url( '/' ) );
     372                $parsed_url = wp_parse_url( $url );
     373                parse_str( $parsed_url['query'], $query_params );
     374                $this->assertArrayNotHasKey( 'customize_messenger_channel', $query_params );
     375                $this->assertArrayHasKey( 'customize_changeset_uuid', $query_params );
     376                $this->assertArrayHasKey( 'customize_theme', $query_params );
     377                $this->assertEquals( $uuid, $query_params['customize_changeset_uuid'] );
     378                $this->assertEquals( 'twentyfifteen', $query_params['customize_theme'] );
     379
     380                $uuid = wp_generate_uuid4();
     381                $wp_customize = new WP_Customize_Manager( array(
     382                        'changeset_uuid' => $uuid,
     383                        'messenger_channel' => null,
     384                        'theme' => 'twentyfifteen',
     385                ) );
     386                $url = $wp_customize->add_state_query_params( 'http://not-allowed.example.com/?q=1' );
     387                $parsed_url = wp_parse_url( $url );
     388                parse_str( $parsed_url['query'], $query_params );
     389                $this->assertArrayNotHasKey( 'customize_messenger_channel', $query_params );
     390                $this->assertArrayNotHasKey( 'customize_changeset_uuid', $query_params );
     391                $this->assertArrayNotHasKey( 'customize_theme', $query_params );
     392        }
     393
     394        /**
     395         * Test WP_Customize_Manager::save_changeset_post().
     396         *
     397         * @ticket 30937
     398         * @covers WP_Customize_Manager::save_changeset_post()
     399         */
     400        function test_save_changeset_post_without_theme_activation() {
     401                wp_set_current_user( self::$admin_user_id );
     402
     403                $did_action = array(
     404                        'customize_save_validation_before' => did_action( 'customize_save_validation_before' ),
     405                        'customize_save' => did_action( 'customize_save' ),
     406                        'customize_save_after' => did_action( 'customize_save_after' ),
     407                );
     408                $uuid = wp_generate_uuid4();
     409
     410                $manager = new WP_Customize_Manager( array(
     411                        'changeset_uuid' => $uuid,
     412                ) );
     413                $manager->register_controls();
     414                $manager->set_post_value( 'blogname', 'Changeset Title' );
     415                $manager->set_post_value( 'blogdescription', 'Changeset Tagline' );
     416
     417                $r = $manager->save_changeset_post( array(
     418                        'status' => 'auto-draft',
     419                        'title' => 'Auto Draft',
     420                        'date_gmt' => '2010-01-01 00:00:00',
     421                        'data' => array(
     422                                'blogname' => array(
     423                                        'value' => 'Overridden Changeset Title',
     424                                ),
     425                                'blogdescription' => array(
     426                                        'custom' => 'something',
     427                                ),
     428                        ),
     429                ) );
     430                $this->assertInternalType( 'array', $r );
     431
     432                $this->assertEquals( $did_action['customize_save_validation_before'] + 1, did_action( 'customize_save_validation_before' ) );
     433
     434                $post_id = $manager->find_changeset_post_id( $uuid );
     435                $this->assertNotNull( $post_id );
     436                $saved_data = json_decode( get_post( $post_id )->post_content, true );
     437                $this->assertEquals( $manager->unsanitized_post_values(), wp_list_pluck( $saved_data, 'value' ) );
     438                $this->assertEquals( 'Overridden Changeset Title', $saved_data['blogname']['value'] );
     439                $this->assertEquals( 'something', $saved_data['blogdescription']['custom'] );
     440                $this->assertEquals( 'Auto Draft', get_post( $post_id )->post_title );
     441                $this->assertEquals( 'auto-draft', get_post( $post_id )->post_status );
     442                $this->assertEquals( '2010-01-01 00:00:00', get_post( $post_id )->post_date_gmt );
     443                $this->assertNotEquals( 'Changeset Title', get_option( 'blogname' ) );
     444                $this->assertArrayHasKey( 'setting_validities', $r );
     445
     446                // Test saving with invalid settings, ensuring transaction blocked.
     447                $previous_saved_data = $saved_data;
     448                $manager->add_setting( 'foo_unauthorized', array(
     449                        'capability' => 'do_not_allow',
     450                ) );
     451                $manager->add_setting( 'baz_illegal', array(
     452                        'validate_callback' => array( $this, 'return_illegal_error' ),
     453                ) );
     454                $r = $manager->save_changeset_post( array(
     455                        'status' => 'auto-draft',
     456                        'data' => array(
     457                                'blogname' => array(
     458                                        'value' => 'OK',
     459                                ),
     460                                'foo_unauthorized' => array(
     461                                        'value' => 'No',
     462                                ),
     463                                'bar_unknown' => array(
     464                                        'value' => 'No',
     465                                ),
     466                                'baz_illegal' => array(
     467                                        'value' => 'No',
     468                                ),
     469                        ),
     470                ) );
     471                $this->assertInstanceOf( 'WP_Error', $r );
     472                $this->assertEquals( 'transaction_fail', $r->get_error_code() );
     473                $this->assertInternalType( 'array', $r->get_error_data() );
     474                $this->assertArrayHasKey( 'setting_validities', $r->get_error_data() );
     475                $error_data = $r->get_error_data();
     476                $this->assertArrayHasKey( 'blogname', $error_data['setting_validities'] );
     477                $this->assertTrue( $error_data['setting_validities']['blogname'] );
     478                $this->assertArrayHasKey( 'foo_unauthorized', $error_data['setting_validities'] );
     479                $this->assertInstanceOf( 'WP_Error', $error_data['setting_validities']['foo_unauthorized'] );
     480                $this->assertEquals( 'unauthorized', $error_data['setting_validities']['foo_unauthorized']->get_error_code() );
     481                $this->assertArrayHasKey( 'bar_unknown', $error_data['setting_validities'] );
     482                $this->assertInstanceOf( 'WP_Error', $error_data['setting_validities']['bar_unknown'] );
     483                $this->assertEquals( 'unrecognized', $error_data['setting_validities']['bar_unknown']->get_error_code() );
     484                $this->assertArrayHasKey( 'baz_illegal', $error_data['setting_validities'] );
     485                $this->assertInstanceOf( 'WP_Error', $error_data['setting_validities']['baz_illegal'] );
     486                $this->assertEquals( 'illegal', $error_data['setting_validities']['baz_illegal']->get_error_code() );
     487
     488                // Since transactional, ensure no changes have been made.
     489                $this->assertEquals( $previous_saved_data, json_decode( get_post( $post_id )->post_content, true ) );
     490
     491                // Attempt a non-transactional/incremental update.
     492                $manager = new WP_Customize_Manager( array(
     493                        'changeset_uuid' => $uuid,
     494                ) );
     495                $manager->register_controls(); // That is, register settings.
     496                $r = $manager->save_changeset_post( array(
     497                        'status' => null,
     498                        'data' => array(
     499                                'blogname' => array(
     500                                        'value' => 'Non-Transactional \o/ <script>unsanitized</script>',
     501                                ),
     502                                'bar_unknown' => array(
     503                                        'value' => 'No',
     504                                ),
     505                        ),
     506                ) );
     507                $this->assertInternalType( 'array', $r );
     508                $this->assertArrayHasKey( 'setting_validities', $r );
     509                $this->assertTrue( $r['setting_validities']['blogname'] );
     510                $this->assertInstanceOf( 'WP_Error', $r['setting_validities']['bar_unknown'] );
     511                $saved_data = json_decode( get_post( $post_id )->post_content, true );
     512                $this->assertNotEquals( $previous_saved_data, $saved_data );
     513                $this->assertEquals( 'Non-Transactional \o/ <script>unsanitized</script>', $saved_data['blogname']['value'] );
     514
     515                // Ensure the filter applies.
     516                $customize_changeset_save_data_call_count = $this->customize_changeset_save_data_call_count;
     517                add_filter( 'customize_changeset_save_data', array( $this, 'filter_customize_changeset_save_data' ), 10, 2 );
     518                $manager->save_changeset_post( array(
     519                        'status' => null,
     520                        'data' => array(
     521                                'blogname' => array(
     522                                        'value' => 'Filtered',
     523                                ),
     524                        ),
     525                ) );
     526                $this->assertEquals( $customize_changeset_save_data_call_count + 1, $this->customize_changeset_save_data_call_count );
     527
     528                // Publish the changeset.
     529                $manager = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     530                $manager->register_controls();
     531                $GLOBALS['wp_customize'] = $manager;
     532                $r = $manager->save_changeset_post( array(
     533                        'status' => 'publish',
     534                        'data' => array(
     535                                'blogname' => array(
     536                                        'value' => 'Do it live \o/',
     537                                ),
     538                        ),
     539                ) );
     540                $this->assertInternalType( 'array', $r );
     541                $this->assertEquals( 'Do it live \o/', get_option( 'blogname' ) );
     542                $this->assertEquals( 'trash', get_post_status( $post_id ) ); // Auto-trashed.
     543
     544                // Test revisions.
     545                add_post_type_support( 'customize_changeset', 'revisions' );
     546                $uuid = wp_generate_uuid4();
     547                $manager = new WP_Customize_Manager( array( 'changeset_uuid' => $uuid ) );
     548                $manager->register_controls();
     549                $GLOBALS['wp_customize'] = $manager;
     550
     551                $manager->set_post_value( 'blogname', 'Hello Surface' );
     552                $manager->save_changeset_post( array( 'status' => 'auto-draft' ) );
     553
     554                $manager->set_post_value( 'blogname', 'Hello World' );
     555                $manager->save_changeset_post( array( 'status' => 'draft' ) );
     556                $this->assertTrue( wp_revisions_enabled( get_post( $manager->changeset_post_id() ) ) );
     557
     558                $manager->set_post_value( 'blogname', 'Hello Solar System' );
     559                $manager->save_changeset_post( array( 'status' => 'draft' ) );
     560
     561                $manager->set_post_value( 'blogname', 'Hello Galaxy' );
     562                $manager->save_changeset_post( array( 'status' => 'draft' ) );
     563                $this->assertCount( 3, wp_get_post_revisions( $manager->changeset_post_id() ) );
     564        }
     565
     566        /**
     567         * Call count for customize_changeset_save_data filter.
     568         *
     569         * @var int
     570         */
     571        protected $customize_changeset_save_data_call_count = 0;
     572
     573        /**
     574         * Filter customize_changeset_save_data.
     575         *
     576         * @param array $data    Data.
     577         * @param array $context Context.
     578         * @returns array Data.
     579         */
     580        function filter_customize_changeset_save_data( $data, $context ) {
     581                $this->customize_changeset_save_data_call_count += 1;
     582                $this->assertInternalType( 'array', $data );
     583                $this->assertInternalType( 'array', $context );
     584                $this->assertArrayHasKey( 'uuid', $context );
     585                $this->assertArrayHasKey( 'title', $context );
     586                $this->assertArrayHasKey( 'status', $context );
     587                $this->assertArrayHasKey( 'date_gmt', $context );
     588                $this->assertArrayHasKey( 'post_id', $context );
     589                $this->assertArrayHasKey( 'previous_data', $context );
     590                $this->assertArrayHasKey( 'manager', $context );
     591                return $data;
     592        }
     593
     594        /**
     595         * Return illegal error.
     596         *
     597         * @return WP_Error Error.
     598         */
     599        function return_illegal_error() {
     600                return new WP_Error( 'illegal' );
     601        }
     602
     603        /**
     604         * Test WP_Customize_Manager::save_changeset_post().
     605         *
     606         * @ticket 30937
     607         * @covers WP_Customize_Manager::save_changeset_post()
     608         * @covers WP_Customize_Manager::update_stashed_theme_mod_settings()
     609         */
     610        function test_save_changeset_post_with_theme_activation() {
     611                wp_set_current_user( self::$admin_user_id );
     612
     613                $stashed_theme_mods = array(
     614                        'twentyfifteen' => array(
     615                                'background_color' => array(
     616                                        'value' => '#123456',
     617                                ),
     618                        ),
     619                );
     620                update_option( 'customize_stashed_theme_mods', $stashed_theme_mods );
     621                $uuid = wp_generate_uuid4();
     622                $manager = new WP_Customize_Manager( array(
     623                        'changeset_uuid' => $uuid,
     624                        'theme' => 'twentyfifteen',
     625                ) );
     626                $manager->register_controls();
     627                $GLOBALS['wp_customize'] = $manager;
     628
     629                $manager->set_post_value( 'blogname', 'Hello 2015' );
     630                $post_values = $manager->unsanitized_post_values();
     631                $manager->save_changeset_post( array( 'status' => 'publish' ) ); // Activate.
     632
     633                $this->assertEquals( '#123456', $post_values['background_color'] );
     634                $this->assertEquals( 'twentyfifteen', get_stylesheet() );
     635                $this->assertEquals( 'Hello 2015', get_option( 'blogname' ) );
     636        }
     637
     638        /**
     639         * Test WP_Customize_Manager::is_cross_domain().
     640         *
     641         * @ticket 30937
     642         * @covers WP_Customize_Manager::is_cross_domain()
     643         */
     644        function test_is_cross_domain() {
     645                $wp_customize = new WP_Customize_Manager();
     646
     647                update_option( 'home', 'http://example.com' );
     648                update_option( 'siteurl', 'http://example.com' );
     649                $this->assertFalse( $wp_customize->is_cross_domain() );
     650
     651                update_option( 'home', 'http://example.com' );
     652                update_option( 'siteurl', 'https://admin.example.com' );
     653                $this->assertTrue( $wp_customize->is_cross_domain() );
     654        }
     655
     656        /**
     657         * Test WP_Customize_Manager::get_allowed_urls().
     658         *
     659         * @ticket 30937
     660         * @covers WP_Customize_Manager::get_allowed_urls()
     661         */
     662        function test_get_allowed_urls() {
     663                $wp_customize = new WP_Customize_Manager();
     664                $this->assertFalse( is_ssl() );
     665                $this->assertFalse( $wp_customize->is_cross_domain() );
     666                $allowed = $wp_customize->get_allowed_urls();
     667                $this->assertEquals( $allowed, array( home_url( '/', 'http' ) ) );
     668
     669                add_filter( 'customize_allowed_urls', array( $this, 'filter_customize_allowed_urls' ) );
     670                $allowed = $wp_customize->get_allowed_urls();
     671                $this->assertEqualSets( $allowed, array( 'http://headless.example.com/', home_url( '/', 'http' ) ) );
     672        }
     673
     674        /**
     675         * Callback for customize_allowed_urls filter.
     676         *
     677         * @param array $urls URLs.
     678         * @return array URLs.
     679         */
     680        function filter_customize_allowed_urls( $urls ) {
     681                $urls[] = 'http://headless.example.com/';
     682                return $urls;
    56683        }
    57684
     
    91718         * @ticket 30988
    92719         */
    93         function test_unsanitized_post_values() {
     720        function test_unsanitized_post_values_from_input() {
     721                wp_set_current_user( self::$admin_user_id );
    94722                $manager = $this->manager;
    95723
     
    101729                $post_values = $manager->unsanitized_post_values();
    102730                $this->assertEquals( $customized, $post_values );
     731                $this->assertEmpty( $manager->unsanitized_post_values( array( 'exclude_post_data' => true ) ) );
     732
     733                $manager->set_post_value( 'foo', 'BAR' );
     734                $post_values = $manager->unsanitized_post_values();
     735                $this->assertEquals( 'BAR', $post_values['foo'] );
     736                $this->assertEmpty( $manager->unsanitized_post_values( array( 'exclude_post_data' => true ) ) );
     737
     738                // If user is unprivileged, the post data is ignored.
     739                wp_set_current_user( 0 );
     740                $this->assertEmpty( $manager->unsanitized_post_values() );
     741        }
     742
     743        /**
     744         * Test WP_Customize_Manager::unsanitized_post_values().
     745         *
     746         * @ticket 30937
     747         * @covers WP_Customize_Manager::unsanitized_post_values()
     748         */
     749        function test_unsanitized_post_values_with_changeset_and_stashed_theme_mods() {
     750                wp_set_current_user( self::$admin_user_id );
     751
     752                $stashed_theme_mods = array(
     753                        'twentyfifteen' => array(
     754                                'background_color' => array(
     755                                        'value' => '#000000',
     756                                ),
     757                        ),
     758                );
     759                $stashed_theme_mods[ get_stylesheet() ] = array(
     760                        'background_color' => array(
     761                                'value' => '#FFFFFF',
     762                        ),
     763                );
     764                update_option( 'customize_stashed_theme_mods', $stashed_theme_mods );
     765
     766                $post_values = array(
     767                        'blogdescription' => 'Post Input Tagline',
     768                );
     769                $_POST['customized'] = wp_slash( wp_json_encode( $post_values ) );
     770
     771                $uuid = wp_generate_uuid4();
     772                $changeset_data = array(
     773                        'blogname' => array(
     774                                'value' => 'Changeset Title',
     775                        ),
     776                        'blogdescription' => array(
     777                                'value' => 'Changeset Tagline',
     778                        ),
     779                );
     780                $this->factory()->post->create( array(
     781                        'post_type' => 'customize_changeset',
     782                        'post_status' => 'auto-draft',
     783                        'post_name' => $uuid,
     784                        'post_content' => wp_json_encode( $changeset_data ),
     785                ) );
     786
     787                $manager = new WP_Customize_Manager( array(
     788                        'changeset_uuid' => $uuid,
     789                ) );
     790                $this->assertTrue( $manager->is_theme_active() );
     791
     792                $this->assertArrayNotHasKey( 'background_color', $manager->unsanitized_post_values() );
     793
     794                $this->assertEquals(
     795                        array(
     796                                'blogname' => 'Changeset Title',
     797                                'blogdescription' => 'Post Input Tagline',
     798                        ),
     799                        $manager->unsanitized_post_values()
     800                );
     801                $this->assertEquals(
     802                        array(
     803                                'blogdescription' => 'Post Input Tagline',
     804                        ),
     805                        $manager->unsanitized_post_values( array( 'exclude_changeset' => true ) )
     806                );
     807
     808                $manager->set_post_value( 'blogdescription', 'Post Override Tagline' );
     809                $this->assertEquals(
     810                        array(
     811                                'blogname' => 'Changeset Title',
     812                                'blogdescription' => 'Post Override Tagline',
     813                        ),
     814                        $manager->unsanitized_post_values()
     815                );
     816
     817                $this->assertEquals(
     818                        array(
     819                                'blogname' => 'Changeset Title',
     820                                'blogdescription' => 'Changeset Tagline',
     821                        ),
     822                        $manager->unsanitized_post_values( array( 'exclude_post_data' => true ) )
     823                );
     824
     825                $this->assertEmpty( $manager->unsanitized_post_values( array( 'exclude_post_data' => true, 'exclude_changeset' => true ) ) );
     826
     827                // Test unstashing theme mods.
     828                $manager = new WP_Customize_Manager( array(
     829                        'changeset_uuid' => $uuid,
     830                        'theme' => 'twentyfifteen',
     831                ) );
     832                $this->assertFalse( $manager->is_theme_active() );
     833                $values = $manager->unsanitized_post_values( array( 'exclude_post_data' => true, 'exclude_changeset' => true ) );
     834                $this->assertNotEmpty( $values );
     835                $this->assertArrayHasKey( 'background_color', $values );
     836                $this->assertEquals( '#000000', $values['background_color'] );
     837
     838                $values = $manager->unsanitized_post_values( array( 'exclude_post_data' => false, 'exclude_changeset' => false ) );
     839                $this->assertArrayHasKey( 'background_color', $values );
     840                $this->assertArrayHasKey( 'blogname', $values );
     841                $this->assertArrayHasKey( 'blogdescription', $values );
    103842        }
    104843
     
    109848         */
    110849        function test_post_value() {
     850                wp_set_current_user( self::$admin_user_id );
    111851                $posted_settings = array(
    112852                        'foo' => 'OOF',
     
    132872         */
    133873        function test_invalid_post_value() {
     874                wp_set_current_user( self::$admin_user_id );
    134875                $default_value = 'foo_default';
    135876                $setting = $this->manager->add_setting( 'foo', array(
     
    197938         */
    198939        function test_post_value_validation_sanitization_order() {
     940                wp_set_current_user( self::$admin_user_id );
    199941                $default_value = '0';
    200942                $setting = $this->manager->add_setting( 'numeric', array(
     
    241983         */
    242984        function test_validate_setting_values() {
     985                wp_set_current_user( self::$admin_user_id );
    243986                $setting = $this->manager->add_setting( 'foo', array(
    244987                        'validate_callback' => array( $this, 'filter_customize_validate_foo' ),
     
    3061049
    3071050        /**
     1051         * Test WP_Customize_Manager::validate_setting_values().
     1052         *
     1053         * @ticket 30937
     1054         * @covers WP_Customize_Manager::validate_setting_values()
     1055         */
     1056        function test_validate_setting_values_args() {
     1057                wp_set_current_user( self::$admin_user_id );
     1058                $this->manager->register_controls();
     1059
     1060                $validities = $this->manager->validate_setting_values( array( 'unknown' => 'X' ) );
     1061                $this->assertEmpty( $validities );
     1062
     1063                $validities = $this->manager->validate_setting_values( array( 'unknown' => 'X' ), array( 'validate_existence' => false ) );
     1064                $this->assertEmpty( $validities );
     1065
     1066                $validities = $this->manager->validate_setting_values( array( 'unknown' => 'X' ), array( 'validate_existence' => true ) );
     1067                $this->assertNotEmpty( $validities );
     1068                $this->assertArrayHasKey( 'unknown', $validities );
     1069                $error = $validities['unknown'];
     1070                $this->assertInstanceOf( 'WP_Error', $error );
     1071                $this->assertEquals( 'unrecognized', $error->get_error_code() );
     1072
     1073                $this->manager->get_setting( 'blogname' )->capability = 'do_not_allow';
     1074                $validities = $this->manager->validate_setting_values( array( 'blogname' => 'X' ), array( 'validate_capability' => false ) );
     1075                $this->assertArrayHasKey( 'blogname', $validities );
     1076                $this->assertTrue( $validities['blogname'] );
     1077                $validities = $this->manager->validate_setting_values( array( 'blogname' => 'X' ), array( 'validate_capability' => true ) );
     1078                $this->assertArrayHasKey( 'blogname', $validities );
     1079                $error = $validities['blogname'];
     1080                $this->assertInstanceOf( 'WP_Error', $error );
     1081                $this->assertEquals( 'unauthorized', $error->get_error_code() );
     1082        }
     1083
     1084        /**
    3081085         * Add a length constraint to a setting.
    3091086         *
     
    3291106         */
    3301107        function test_validate_setting_values_validation_sanitization_order() {
     1108                wp_set_current_user( self::$admin_user_id );
    3311109                $setting = $this->manager->add_setting( 'numeric', array(
    3321110                        'validate_callback' => array( $this, 'filter_customize_validate_numeric' ),
     
    3701148         */
    3711149        function test_set_post_value() {
     1150                wp_set_current_user( self::$admin_user_id );
    3721151                $this->manager->add_setting( 'foo', array(
    3731152                        'sanitize_callback' => array( $this, 'sanitize_foo_for_test_set_post_value' ),
     
    4741253                $this->assertFalse( $this->manager->has_published_pages() );
    4751254
    476                 wp_set_current_user( $this->factory()->user->create( array( 'role' => 'editor' ) ) );
     1255                wp_set_current_user( self::$admin_user_id );
    4771256                $this->manager->nav_menus->customize_register();
    4781257                $setting_id = 'nav_menus_created_posts';
     
    4931272         */
    4941273        function test_register_dynamic_settings() {
     1274                wp_set_current_user( self::$admin_user_id );
    4951275                $posted_settings = array(
    4961276                        'foo' => 'OOF',
     
    5921372                $this->assertEquals( home_url( '/' ), $this->manager->get_return_url() );
    5931373
    594                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1374                wp_set_current_user( self::$admin_user_id );
    5951375                $this->assertTrue( current_user_can( 'edit_theme_options' ) );
    5961376                $this->assertEquals( home_url( '/' ), $this->manager->get_return_url() );
     
    6851465         */
    6861466        function test_customize_pane_settings() {
    687                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1467                wp_set_current_user( self::$admin_user_id );
    6881468                $this->manager->register_controls();
    6891469                $this->manager->prepare_controls();
     
    7071487                $this->assertNotEmpty( $data );
    7081488
    709                 $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices' ), array_keys( $data ) );
     1489                $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'changeset', 'timeouts' ), array_keys( $data ) );
    7101490                $this->assertEquals( $autofocus, $data['autofocus'] );
    7111491                $this->assertArrayHasKey( 'save', $data['nonce'] );
     
    7191499         */
    7201500        function test_customize_preview_settings() {
    721                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1501                wp_set_current_user( self::$admin_user_id );
    7221502                $this->manager->register_controls();
    7231503                $this->manager->prepare_controls();
     
    7411521                $this->assertArrayHasKey( 'nonce', $settings );
    7421522                $this->assertArrayHasKey( '_dirty', $settings );
     1523                $this->assertArrayHasKey( 'timeouts', $settings );
     1524                $this->assertArrayHasKey( 'changeset', $settings );
    7431525
    7441526                $this->assertArrayHasKey( 'preview', $settings['nonce'] );
    745                 $this->assertEquals( array( 'foo' ), $settings['_dirty'] );
    7461527        }
    7471528
     
    8151596                $manager->register_controls();
    8161597                $section_id = 'foo-section';
    817                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1598                wp_set_current_user( self::$admin_user_id );
    8181599                $manager->add_section( $section_id, array(
    8191600                        'title'      => 'Section',
     
    8461627        function test_add_section_return_instance() {
    8471628                $manager = new WP_Customize_Manager();
    848                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1629                wp_set_current_user( self::$admin_user_id );
    8491630
    8501631                $section_id = 'foo-section';
     
    8731654        function test_add_setting_return_instance() {
    8741655                $manager = new WP_Customize_Manager();
    875                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1656                wp_set_current_user( self::$admin_user_id );
    8761657
    8771658                $setting_id = 'foo-setting';
     
    9441725        function test_add_panel_return_instance() {
    9451726                $manager = new WP_Customize_Manager();
    946                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1727                wp_set_current_user( self::$admin_user_id );
    9471728
    9481729                $panel_id = 'foo-panel';
     
    9711752                $manager = new WP_Customize_Manager();
    9721753                $section_id = 'foo-section';
    973                 wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     1754                wp_set_current_user( self::$admin_user_id );
    9741755                $manager->add_section( $section_id, array(
    9751756                        'title'    => 'Section',
Note: See TracChangeset for help on using the changeset viewer.