Make WordPress Core


Ignore:
Timestamp:
10/12/2017 04:00:15 AM (9 years ago)
Author:
westonruter
Message:

Customize: Add changeset locking in Customizer to prevent users from overriding each other's changes.

  • Customization locking is checked when changesets are saved and when heartbeat ticks.
  • Lock is lifted immediately upon a user closing the Customizer.
  • Heartbeat is introduced into Customizer.
  • Changes made to user after it was locked by another user are stored as an autosave revision for restoration.
  • Lock notification displays link to preview the other user's changes on the frontend.
  • A user loading a locked Customizer changeset will be presented with an option to take over.
  • Autosave revisions attached to a published changeset are converted into auto-drafts so that they will be presented to users for restoration.
  • Focus constraining is improved in overlay notifications.
  • Escape key is stopped from propagating in overlay notifications, and it dismisses dismissible overlay notifications.
  • Introduces changesetLocked state which is used to disable the Save button and suppress the AYS dialog when leaving the Customizer.
  • Fixes bug where users could be presented with each other's autosave revisions.

Props sayedwp, westonruter, melchoyce.
See #31436, #31897, #39896.
Fixes #42024.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/ajax/CustomizeManager.php

    r41667 r41839  
    517517         *
    518518         * @ticket 39896
    519          * @covers WP_Customize_Manager::handle_dismiss_autosave_request()
     519         * @covers WP_Customize_Manager::handle_dismiss_autosave_or_lock_request()
    520520         * @covers WP_Customize_Manager::dismiss_user_auto_draft_changesets()
    521521         */
    522         public function test_handle_dismiss_autosave_request() {
     522        public function test_handle_dismiss_autosave_or_lock_request() {
    523523                $uuid = wp_generate_uuid4();
    524524                $wp_customize = $this->set_up_valid_state( $uuid );
    525525
    526                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     526                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    527527                $this->assertFalse( $this->_last_response_parsed['success'] );
    528528                $this->assertEquals( 'invalid_nonce', $this->_last_response_parsed['data'] );
    529529
    530                 $nonce = wp_create_nonce( 'customize_dismiss_autosave' );
     530                $nonce = wp_create_nonce( 'customize_dismiss_autosave_or_lock' );
    531531                $_POST['nonce'] = $_GET['nonce'] = $_REQUEST['nonce'] = $nonce;
    532                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     532
     533                $_POST['dismiss_lock'] = $_GET['dismiss_lock'] = $_REQUEST['dismiss_lock'] = true;
     534                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
     535                $this->assertFalse( $this->_last_response_parsed['success'] );
     536                $this->assertEquals( 'no_changeset_to_dismiss_lock', $this->_last_response_parsed['data'] );
     537
     538                $_POST['dismiss_autosave'] = $_GET['dismiss_autosave'] = $_REQUEST['dismiss_autosave'] = true;
     539                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    533540                $this->assertFalse( $this->_last_response_parsed['success'] );
    534541                $this->assertEquals( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
     
    560567                        $this->assertFalse( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
    561568                }
    562                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     569                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    563570                $this->assertTrue( $this->_last_response_parsed['success'] );
    564571                $this->assertEquals( 'auto_draft_dismissed', $this->_last_response_parsed['data'] );
     
    573580
    574581                // Subsequent test results in none dismissed.
    575                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     582                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    576583                $this->assertFalse( $this->_last_response_parsed['success'] );
    577584                $this->assertEquals( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
     
    586593                        'status' => 'draft',
    587594                ) );
     595
     596                $_POST['dismiss_autosave'] = $_GET['dismiss_autosave'] = $_REQUEST['dismiss_autosave'] = false;
     597                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
     598                $this->assertTrue( $this->_last_response_parsed['success'] );
     599                $this->assertEquals( 'changeset_lock_dismissed', $this->_last_response_parsed['data'] );
     600
     601                $_POST['dismiss_autosave'] = $_GET['dismiss_autosave'] = $_REQUEST['dismiss_autosave'] = true;
    588602                $this->assertNotInstanceOf( 'WP_Error', $r );
    589603                $this->assertFalse( wp_get_post_autosave( $wp_customize->changeset_post_id() ) );
     
    591605
    592606                // Since no autosave yet, confirm no action.
    593                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     607                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    594608                $this->assertFalse( $this->_last_response_parsed['success'] );
    595609                $this->assertEquals( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
     
    611625
    612626                // Confirm autosave gets deleted.
    613                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     627                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    614628                $this->assertTrue( $this->_last_response_parsed['success'] );
    615629                $this->assertEquals( 'autosave_revision_deleted', $this->_last_response_parsed['data'] );
     
    617631
    618632                // Since no autosave yet, confirm no action.
    619                 $this->make_ajax_call( 'customize_dismiss_autosave' );
     633                $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    620634                $this->assertFalse( $this->_last_response_parsed['success'] );
    621635                $this->assertEquals( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
Note: See TracChangeset for help on using the changeset viewer.